Zum Inhalt springen
Zum Inhalt springen

Referenz / CLI

Maschinell übersetzte Seite

Diese Seite wurde automatisch übersetzt und kann daher Fehler oder seltsame Formulierungen enthalten. Die englische Version ist die maßgebliche Quelle. Das englische Original lesen.

verbatra extract

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

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

verbatra extract [flags]

Beispiele

# 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

FlagArgumentStandardWirkung
--dry-runkeinsausmelden, was ergänzt würde, und nichts schreiben

Außerdem nimmt der Befehl die globalen Flags --cwd, --config und --json; die Quellverzeichnisse aus extract werden von der Projektwurzel aus aufgelöst.

Verhalten

Konfiguration

extract wird vom extract-Block 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.

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

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:

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

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

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 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 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.

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

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 alsWann
dynamicder 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.
conflictsein Key steht an zwei Aufrufen mit unterschiedlichen Standardwerten. Keiner der Werte wird geschrieben, damit der Katalog nie von der Durchlaufreihenfolge abhängt.
withoutDefaultein Key wurde mit leerem Wert ergänzt, weil sein Aufruf keinen Standardwert hatte. Füll ihn aus und übersetze dann.
diagnosticseine 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

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

Schema: extract-envelope.json validiert den ganzen Envelope; Schemas listet die übrigen auf.

Mit --json trägt der Envelope ein Ergebnis:

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

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:

Ausgabe
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.

Exit-Codes

CodeBedeutung
0der Scan ist gelaufen, egal was er gefunden hat
2konnte 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.

Siehe auch

Auf GitHub bearbeiten

Auf dieser Seite