---
title: "verbatra extract"
description: "Durchsuche deinen Anwendungscode nach Übersetzungsaufrufen und ergänze die neuen Keys in der Quell-Locale-Datei."
type: "reference"
---
# verbatra extract

Durchsuche deinen Anwendungscode nach Übersetzungsaufrufen und ergänze die neuen Keys in der Quell-Locale-Datei.

<AvailableFrom version="0.11.0" />

Starte bei deinem Code statt bei einer Locale-Datei. `extract` durchläuft die konfigurierten Quellverzeichnisse, findet darin die Übersetzungsaufrufe und ergänzt jeden Key, den die Quell-Locale-Datei noch nicht hat. So wird verbatra auch in einem Projekt nutzbar, das noch nicht internationalisiert ist, und es kostet nichts: kein Provider, kein API-Key, keine Netzwerkanfrage.

## Synopsis [#synopsis]

```bash
verbatra extract [flags]
```

## Beispiele [#beispiele]

```bash
# add every new key found in your source to the source locale file
verbatra extract

# preview the keys that would be added, write nothing
verbatra extract --dry-run

# machine-readable result for a CI step
verbatra extract --json
```

## Flags [#flags]

| Flag | Argument | Standard | Wirkung |
| --- | --- | --- | --- |
| `--dry-run` | keins | aus | melden, was ergänzt würde, und nichts schreiben |

Außerdem nimmt der Befehl die [globalen Flags](https://verbatra.kreitz-webdev.de/de/docs/cli.md#globale-flags) `--cwd`, `--config` und `--json`; die Quellverzeichnisse aus `extract` werden von der [Projektwurzel](https://verbatra.kreitz-webdev.de/de/docs/config-file.md#das-arbeitsverzeichnis-und-env) aus aufgelöst.

## Verhalten [#verhalten]

### Konfiguration [#konfiguration]

`extract` wird vom [`extract`-Block](https://verbatra.kreitz-webdev.de/de/docs/config-file.md#extract) in deiner Konfiguration gesteuert. Ein Lauf ohne diesen Block scheitert mit `EXTRACT_NOT_CONFIGURED` und Exit `2`. Für `i18next-json` schreibt `verbatra init` den Block als Kommentar in die erzeugte Konfiguration; entkommentiere ihn und passe `roots` an.

```ts title="verbatra.config.ts"
import { defineConfig } from "@verbatra/cli";

export default defineConfig({
  sourceLocale: "en",
  targetLocales: ["de", "fr"],
  format: "i18next-json",
  files: { pattern: "locales/{locale}.json" },
  provider: { id: "gemini", options: { model: "gemini-2.5-flash", maxOutputTokens: 4096 } },
  extract: {
    framework: "i18next",
    roots: ["src"],
  },
});
```

### Was er findet [#was-er-findet]

Das Framework `i18next` liest die Aufrufformen `t(...)`, `$t(...)` und `<object>.t(...)` in `.ts`-, `.tsx`-, `.js`-, `.jsx`-, `.mjs`-, `.cjs`-, `.mts`- und `.cts`-Dateien, jeweils auch als optionalen Aufruf und mit expliziter Typargumentliste. Der Key ist das erste Argument; ein Standardwert ist das zweite Argument oder ein Feld `defaultValue` im Options-Objekt:

```ts
t("nav.home");                              // key only, written with an empty value
t("nav.away", "Away");                      // positional default
t("nav.help", { defaultValue: "Help" });    // default on the options object
t?.("nav.back");                            // optional call
t<string>("nav.next");                      // explicit type argument
```

Kommentare, Strings und reguläre Ausdrücke werden verstanden, ein Aufruf in einem Kommentar oder ein `t(` in Anführungszeichen innerhalb eines Strings wird also nicht aufgegriffen. Key und Standardwert müssen jeweils ein vollständiges Literal sein: `t("user." + id)` wird als dynamisch gemeldet, und ein zusammengesetzter Standardwert ergänzt den Key ohne Standardwert statt mit einem abgeschnittenen. Ein Key mit leerem Pfadsegment (`t("user.")`, `t(".lead")`, `t("a..b")`) würde unter einem namenlosen Kind landen, das deine Anwendung nie liest, und wird deshalb ebenfalls als dynamisch gemeldet.

### Namespaces werden noch nicht aufgelöst [#namespaces-werden-noch-nicht-aufgelöst]

Ein Key mit Namespace wie `t("common:nav.home")` wird als dynamisch gemeldet und nie geschrieben: Eine verbatra-Konfiguration adressiert genau eine Katalogdatei, es gibt also keinen Ort, der das bedeutet, was dein i18next-Setup damit meint. Nennt dein Projekt an jedem Aufruf einen Namespace, ergänzt der Lauf nichts. Heute ist `extract` nützlich in einem Projekt, das einen Namespace behält und seine Keys ohne Präfix schreibt.

### Was er schreibt [#was-er-schreibt]

Nur die Quell-Locale-Datei, und nur Keys, die wirklich neu sind:

- Ein Key, der schon im Katalog steht, behält seinen Wert genau so, wie er ist; ein Standardwert am Aufruf überschreibt nie eine Bearbeitung.
- Ein Key, den der Katalog nur in Pluralformen führt, gilt als vorhanden: `t("cart.items", { count })` fügt neben `cart.items_one` und `cart.items_other` nichts hinzu, und das gilt genauso für einen gettext-Eintrag mit `msgid_plural` und eine Android-`<plurals>`-Ressource. In einem Format, das Pluralformen nicht markiert, etwa YAML, zählt jeder Key mit einem i18next-Plural-Suffix.
- Ein Katalog-Key, den kein Aufruf erwähnt, bleibt stehen. `extract` löscht nie; [`verbatra diff --unused`](https://verbatra.kreitz-webdev.de/de/docs/cli/diff.md#ungenutzte-quell-keys) listet diese Keys.
- Ein Lauf, der nichts Neues findet, schreibt nichts, die Datei bleibt also byte-identisch.
- Eine Ziel-Locale-Datei wird nie geschrieben. Lass danach [`verbatra translate`](https://verbatra.kreitz-webdev.de/de/docs/cli/translate.md) laufen, um die neuen Keys zu füllen. Ein Key mit leerem Wert wird übersprungen, bis du seinen Quelltext schreibst, und der Lauf nennt ihn mit [`SOURCE_VALUE_EMPTY`](https://verbatra.kreitz-webdev.de/de/docs/error-codes.md#source_value_empty).

Kataloge in `xliff` und `apple-xcstrings` werden nie aus dem Nichts erzeugt: Leg den Quellkatalog zuerst an (den `.xcstrings`-Katalog in Xcode), dann ergänzt `extract` ihn.

### Was er meldet, statt zu raten [#was-er-meldet-statt-zu-raten]

Alles, was der Scan nicht auflösen kann, kommt als Daten zurück, eine sperrige Datei bricht einen Lauf also nie ab. Keiner dieser Befunde ändert den Exit-Code.

| Gemeldet als | Wann |
| --- | --- |
| `dynamic` | der Key ist kein einzelner vollständiger statischer String oder beschreibt einen Pfad, den verbatra nicht adressieren kann: eine Variable, ein Member-Ausdruck, ein Template-Literal mit Ausdruck, eine Verkettung, ein Key mit Namespace oder ein leeres Pfadsegment. Er wird nie geschrieben. |
| `conflicts` | ein Key steht an zwei Aufrufen mit unterschiedlichen Standardwerten. Keiner der Werte wird geschrieben, damit der Katalog nie von der Durchlaufreihenfolge abhängt. |
| `withoutDefault` | ein Key wurde mit leerem Wert ergänzt, weil sein Aufruf keinen Standardwert hatte. Füll ihn aus und übersetze dann. |
| `diagnostics` | eine Datei oder ein Verzeichnis konnte nicht bis zum Ende gelesen werden: verschwunden, über der Grenze von 2.000.000 Byte, der Scan ist daran gescheitert, oder ein nicht geschlossener Kommentar, Template-Literal, JSX-Element oder String hat den Rest abgebrochen. Was vorher gelesen wurde, wird trotzdem gemeldet. |

### Grenzen des Scans [#grenzen-des-scans]

Nichts außerhalb der konfigurierten `roots` wird gelesen. `node_modules`, `.git`, `.next`, `.turbo`, `.verbatra`, `dist`, `build` und `coverage` werden immer übersprungen, `extract.exclude` ergänzt eigene Verzeichnisnamen, und symbolischen Links wird nicht gefolgt. Das Ergebnis trägt nur Keys, Werte und Datei- und Zeilenangaben, nie den Inhalt einer Quelldatei.

### JSON-Ausgabe [#json-ausgabe]

Schema: [`extract-envelope.json`](https://verbatra.kreitz-webdev.de/schema/v1/extract-envelope.json) validiert den ganzen Envelope; [Schemas](https://verbatra.kreitz-webdev.de/de/docs/cli/output.md#schemas) listet die übrigen auf.

Mit `--json` trägt der [Envelope](https://verbatra.kreitz-webdev.de/de/docs/cli/output.md#json-ausgabe) ein Ergebnis:

```ts
interface ExtractResult {
  sourcePath: string;          // the source locale file, relative to the project root
  scannedFiles: number;
  added: { key: string; value: string; file: string; line: number }[];
  existingKeys: number;        // keys found that were already in the catalog
  withoutDefault: string[];
  dynamic: { file: string; line: number }[];
  conflicts: { key: string; values: string[]; locations: { file: string; line: number }[] }[];
  diagnostics: { file: string; reason: "unreadable" | "too-large" | "unparseable" | "unreadable-directory" }[];
  written: boolean;            // false for a dry run and for a run that added nothing
  dryRun: boolean;
}
```

### Rückmeldung im Terminal [#rückmeldung-im-terminal]

<AvailableFrom version="0.12.0" />

Die Zusammenfassung geht auf stdout. Auf stderr zählt eine Spinner-Zeile die gescannten Dateien; wurden Keys ergänzt, schlägt ein Hinweis `verbatra translate` vor, nach `--dry-run` denselben extract ohne das Flag. `--quiet` lässt die stderr-Zeilen weg:

```text output
verbatra: scanning the source... done (0.6s)
verbatra extract
  42 files scanned, 18 keys already present
  added 3 keys to locales/en.json
  new keys (3):
    nav.home  src/components/Nav.tsx:14
    nav.away  src/components/Nav.tsx:15
    cart.empty  src/routes/cart.tsx:31
  dynamic keys (1):
    src/routes/product.tsx:88
next: verbatra translate (translate the new keys)
```

Farbe, Spinner und die Variablen dazu findest du unter [Terminalausgabe](https://verbatra.kreitz-webdev.de/de/docs/cli/output.md#terminalausgabe).

## Exit-Codes [#exit-codes]

| Code | Bedeutung |
| --- | --- |
| `0` | der Scan ist gelaufen, egal was er gefunden hat |
| `2` | konnte nicht laufen: ein Verwendungsfehler, kein `extract`-Block, ein nicht auflösbares Format, ein nicht parsebarer Quellkatalog oder ein Quellkatalog, der nicht geschrieben werden konnte |

Es gibt keinen Exit `1`: Dynamische Aufrufe und widersprüchliche Standardwerte sind Befunde, keine Fehlschläge. Den Vertrag, dem jeder Befehl folgt, findest du unter [Exit-Codes](https://verbatra.kreitz-webdev.de/de/docs/cli/output.md#exit-codes).

## Siehe auch [#siehe-auch]

- [Keys aus dem Quellcode extrahieren](https://verbatra.kreitz-webdev.de/de/docs/extract-keys.md) führt durch den Ablauf von der Aufrufstelle bis zum übersetzten Key.
- [Die Konfigurationsdatei](https://verbatra.kreitz-webdev.de/de/docs/config-file.md#extract) dokumentiert den `extract`-Block.
- [`verbatra translate`](https://verbatra.kreitz-webdev.de/de/docs/cli/translate.md) füllt die Ziel-Locales, sobald die neuen Keys existieren.
- [`verbatra types`](https://verbatra.kreitz-webdev.de/de/docs/cli/types.md) deklariert die Keys für TypeScript.
- [`verbatra check`](https://verbatra.kreitz-webdev.de/de/docs/cli/check.md) meldet die Drift, die die neuen Keys erzeugen.
- [Das SDK](https://verbatra.kreitz-webdev.de/de/docs/sdk/inspect.md#extract) bietet dieselbe Fähigkeit als `extract()`.
