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.

Exit-Codes und JSON-Ausgabe

Der Exit-Code-Vertrag, der JSON-Envelope jedes Befehls mit --json, die Codes, die die CLI selbst auslöst, und wie verbatra auf stderr und ins Terminal schreibt.

Alles, worauf sich ein Skript oder CI-Schritt über alle Befehle hinweg verlassen kann. Jede Befehlsseite ergänzt nur, was für diesen Befehl gilt.

Exit-Codes

Der Exit-Code ist der Vertrag, auf den dein CI-Schritt verzweigt:

CodeBedeutung
0Erfolg, je Befehl wie unter der Tabelle aufgeführt
1der Lauf kam durch, aber das Ergebnis ist nicht sauber: translate oder import endete mit mindestens einer fehlgeschlagenen oder unvollständigen Locale, check fand eine Locale nicht synchron (oder mit --qa eine eingecheckte Übersetzung mit einem Integritätsfehler oder mit --strict einer Review-Warnung oder einem unvollständigen Plural, oder mit --require-reviewed eine maschinell geschriebene Übersetzung, die niemand freigegeben hat, oder mit --sensitive Inhalt in Quelldatei oder Glossar, der sensibel aussieht), check --file fand einen Syntax- oder Integritätsfehler in der Datei (oder mit --strict eine Review-Warnung oder einen unvollständigen Plural), diff fand einen fehlenden oder geänderten Key (oder mit --unused fand ein vollständiger Scan einen ungenutzten Quell-Key), report provenance fand verbatra.provenance.json beschädigt oder von einer neueren verbatra-Version geschrieben, doctor fand mindestens eine fehlgeschlagene Prüfung, types --check stellte fest, dass die committete Deklaration veraltet ist, oder studio beziehungsweise mcp scheiterte beim Herunterfahren seines Servers
2konnte nicht laufen: ein Fehler des gesamten Laufs (kaputte Konfiguration, unlesbare Quelle, kaputte Lock-Datei, eine Locale, die der Provider nicht unterstützt), ein Verwendungsfehler (eine leere --locales-Liste, INVALID_LOCALES, oder ein ungültiges --debounce oder --port), ein nicht konfigurierter --locales-Wert (UNKNOWN_LOCALE), init, dem ein benötigtes Flag fehlt, das mehrere passende Formate oder Dateimuster findet, das sich weigert, eine bestehende Konfiguration zu überschreiben, oder das keine gültige Konfiguration anlegen kann, watch, das nicht starten oder nicht stoppen kann, studio, das die Konfiguration nicht laden, @verbatra/studio nicht importieren oder seinen Server nicht starten kann, oder mcp, dem --config einen Pfad nennt, den es nicht gibt, oder das @verbatra/mcp nicht importieren, seinen Server nicht starten oder --redact-values mit dem installierten @verbatra/mcp nicht umsetzen kann (eine fehlende oder ungültige Konfiguration aus der Suche startet ihn unkonfiguriert)
3translate (auch als Dry Run und mit --estimate) in einem rein menschlichen Projekt (provider: { id: "none" }) lief sauber durch, hat aber Keys für eine menschliche Übersetzung übrig gelassen; eine fehlgeschlagene oder teilweise Locale endet weiterhin mit 1
130translate oder import wurde mit Ctrl-C (SIGINT) abgebrochen, nachdem die Schreibsperren freigegeben waren, oder watch, studio oder mcp wurde durch einen zweiten Interrupt zwangsbeendet
143translate oder import wurde mit SIGTERM beendet, nachdem die Schreibsperren freigegeben waren

Exit 0 bedeutet je Befehl:

  • translate oder import: jede Locale wurde vollständig abgeschlossen
  • check: jede Locale ist synchron
  • diff: keine ausstehenden Änderungen
  • report: der Bericht wurde ausgegeben
  • doctor: kein Problem in der Einrichtung
  • extract: der Scan wurde abgeschlossen
  • pseudo: die Pseudolocale wurde erzeugt
  • types: die Deklaration wurde erzeugt
  • export: die Arbeitsmappe wurde geschrieben
  • tmx: der Übersetzungsspeicher wurde importiert oder exportiert
  • init: das Projekt wurde angelegt oder war schon auf dem aktuellen Stand
  • watch, studio oder mcp: wurde sauber beendet
  • --help oder --version: die Hilfe oder die Version wurde ausgegeben

Bei 130 und 143 endet stderr mit verbatra: interrupted (SIGINT), released locks (oder SIGTERM), oder unter --json mit dem Datensatz {"type":"interrupted","signal":"SIGINT","locksReleased":true}. Scheitert das Freigeben der Sperren oder ist es nach 5 Sekunden nicht fertig, sagt die Zeile das stattdessen (could not release locks: <reason> oder lock release did not finish within 5s), und der JSON-Datensatz trägt "locksReleased":false mit "reason":"failed" (plus message) oder "reason":"timed-out" (plus deadlineMs).

Einige Randfälle, die du kennen solltest:

Verfügbar ab 0.9.0
  • Eine unvollständige Locale zählt als Fehlschlag. Das heißt, die Datei wurde geschrieben, aber einige Keys fehlen weiterhin, meist weil ein Provider-Sub-Batch fehlschlug oder das Integritäts-Gate eine Übersetzung abgelehnt hat. Sie endet mit 1 genau wie eine fehlgeschlagene Locale. Um beide auseinanderzuhalten, lies partial in der Zusammenfassung. Ein fehlgeschlagener Sub-Batch hinterlässt an der Locale einen Hinweis SUB_BATCH_FAILED, der den Fehlercode des Providers nennt, oder PROVIDER_CALL_FAILED, wenn der Fehlschlag kein strukturierter Provider-Fehler war.
  • Eine Locale, die der Provider nicht unterstützt, ist ebenfalls ein Fehler des gesamten Laufs, nie eine einzelne fehlgeschlagene Locale. translate (auch ein Dry Run und --estimate), watch beim Start und eine Neuübersetzung eines einzelnen Keys lehnen sie mit LOCALE_UNSUPPORTED_BY_PROVIDER ab und enden mit 2, bevor ein Provider konstruiert oder irgendetwas ausgegeben wird; keine Locale des Laufs hat also begonnen, und nichts wurde geschrieben. Beurteilt wird gegen die Sprachtabelle, die verbatra für DeepL und Google Cloud Translation mitliefert; ein LLM-Provider akzeptiert jede Locale. Lass die Locale mit --locales weg, um die anderen zu übersetzen, und führe verbatra doctor --locales aus, um zu sehen, warum. Siehe Sprachunterstützung.
  • Eine kaputte Lock-Datei ist bei translate wie bei import ein Fehler des gesamten Laufs, nie eine einzelne fehlgeschlagene Locale. Sie ist eine einzige gemeinsame Datei, deshalb bricht ein Lauf, dessen Lock-Datei mittendrin kaputtgeht, mit 2 ab, statt die restlichen Locales weiter abzuarbeiten. Was vor dem Abbruch geschrieben wurde, bleibt auf der Platte: Repariere die Lock-Datei und starte den Befehl erneut.
  • Ein einzelner Interrupt ist ein sauberer Stopp, und alle drei langlaufenden Befehle (watch, studio und mcp) enden dabei mit 0. Gehe darüber hinaus nicht davon aus, dass sie sich gleich verhalten: Scheitert der Stopp selbst, endet watch mit 2, während studio und mcp mit 1 enden.
  • Ein fehlgeschlagener Lauf während watch erscheint als Datensatz im Ausgabestrom, nie als Exit-Code ungleich null.
  • export hat keinen Fehlermodus pro Locale: Der Befehl endet mit 0 oder 2, nie mit 1.
  • doctor liest eine kaputte Konfiguration anders als jeder andere Befehl: Eine Konfiguration, die die Suche nicht findet, oder eine, die die Validierung nicht besteht, ist eine fehlgeschlagene Prüfung und Exit 1, denn genau das zu melden ist die Aufgabe des Befehls. Exit 2 gibt es nur, wenn er überhaupt nicht laufen kann, etwa bei einem explizit angegebenen --config-Pfad, der nicht existiert.
  • Ein Fehlermodus liegt außerhalb des Vertrags: ein Parse-Fehler, der kein Verwendungsfehler ist, wird weitergeworfen, und das Binary fängt ihn nicht ab. Damit greift Nodes Standardverhalten für eine unbehandelte Rejection statt eines der sechs Codes.
  • Ein geschützter Key (ein veralteter Wert, den ein Mensch geschrieben, importiert oder außerhalb von verbatra geändert hat, oder ein gepinnter Key) ändert den Exit-Code von translate in einem Projekt mit Provider nicht: Der Befehl endet mit 0 und sagt auf stderr, wie viele Keys er übrig gelassen hat (gepinnte Keys zählen nicht mit). check endet dafür trotzdem mit 1, weil der Key veraltet bleibt, bis ein Mensch ihn auflöst. In einem rein menschlichen Projekt zählt er zum Exit 3.

JSON-Ausgabe

Jeder Befehl außer studio und mcp akzeptiert --json für maschinenlesbare Ausgabe auf stdout: translate, watch, check, diff, report, export, import, tmx, doctor, pseudo, types, extract und init. Jeder Datensatz ist eine Zeile, und jeder Datensatz steckt im selben Envelope. Du verzweigst also auf ein einziges Feld und musst nie raten, von welchem Befehl die Daten stammen, die du gerade in der Hand hast:

type Envelope<TResult> =
  | { ok: true; version: 1; command: string; result: TResult }
  | {
      ok: false;
      version: 1;
      command: string | null;
      code: string;
      message: string;
      causeCode?: string; // the code of the error this one wraps, when it has one
      candidates?: string[]; // the values to choose from, on an error that has them
      missing?: string[]; // the flags still to pass, on an init usage error
      hint?: string; // the next step that resolves the error, when there is one
    };

version ist die Version dieser Envelope-Form, nicht die Version des Pakets. Es ist eine ganze Zahl, du vergleichst sie also mit ===, statt einen Bereich zu parsen, und sie ändert sich nur, wenn ein bestehendes Feld seine Bedeutung ändert oder verschwindet. Neue Felder können hinzukommen, ohne dass die Version steigt; ignoriere also die, die du nicht kennst.

Ein Lauf, der als Ganzes fehlschlägt, schreibt genau einen ok: false-Datensatz auf stdout und endet mit 2. Sein code ist derselbe stabile Fehlercode, den auch die stderr-Zeile trägt, und damit das, worauf du verzweigst:

{ "ok": false, "version": 1, "command": "translate", "code": "CONFIG_INVALID", "message": "..." }

command ist nur dann null, wenn der Fehlschlag eintrat, bevor ein Unterbefehl aufgelöst war. candidates erscheint nur bei einem Fehler, der dich wählen lässt, etwa FORMAT_AMBIGUOUS von init, und listet die Werte auf, aus denen du wählst. missing erscheint bei einem Verwendungsfehler von init, der Flags unbeantwortet lässt, und nennt jedes Flag, das du noch übergeben musst. causeCode erscheint, wenn der Fehler einen anderen Fehler mit Code umhüllt, etwa ein PROVIDER_CONSTRUCTION_FAILED mit der Ursache MISSING_API_KEY; die stderr-Zeile endet dann mit (cause: MISSING_API_KEY).

Verfügbar ab 0.12.0

hint erscheint, wenn der Fehler einen nächsten Schritt hat: einen kurzen Satz im Imperativ, der ihn behebt, etwa "Set GEMINI_API_KEY in the environment, or, with the CLI, in a .env file in the project directory." für einen fehlenden Key oder "Run `verbatra check --help` to see the options and arguments it accepts." für einen USAGE_ERROR. Handle danach, statt message zu parsen. Er nennt Variablen, Flags und Pfade, nie den Wert eines Keys. Jeder Code aus dem SDK, von einem Provider und von einem Format-Adapter hat einen (das SDK exportiert denselben Text als errorHint), und ebenso jeder CLI-Fehlercode außer CLI_ERROR. Ohne --json folgt derselbe Text der Fehlerzeile auf stderr als next: ..., außer --quiet ist gesetzt. mcp --json ist die Ausnahme: Es wird mit einer einzigen USAGE_ERROR-Zeile auf stderr abgelehnt, ohne Envelope und ohne next:. Startfehler von studio und mcp bekommen ebenfalls keine next:-Zeile.

Das result eines erfolgreichen Envelopes ist bei jedem Befehl anders und steht auf seiner Seite unter JSON-Ausgabe: extract, translate, watch, check, diff, report, doctor, pseudo, types, export, import, tmx, init.

Schemas Verfügbar ab 0.12.0

Jeder Datensatz, den --json ausgibt, hat ein JSON Schema (Draft 2020-12). Die Schemas liegen in den npm-Paketen und sind unter festen URLs erreichbar, damit ein Skript, ein Agent oder ein Editor die Ausgabe prüfen kann, statt Prosa zu lesen. Jedes Ausgabe-Schema erlaubt Eigenschaften, die es nicht aufführt, so wie es der Envelope-Vertrag oben verspricht; behalte das bei, wenn du eines kopierst. Das Konfigurationsschema ist die bewusste Ausnahme: Es beschreibt, was du schreibst, und lehnt deshalb einen unbekannten Key ab, um einen Tippfehler zu erkennen.

DokumentURLDatei im Paket
Jeder Envelope, Erfolg oder Fehlerenvelope.json@verbatra/cli/schemas/envelope.json
Der Envelope eines Befehls, mit seinem resulthttps://verbatra.kreitz-webdev.de/schema/v1/<command>-envelope.json@verbatra/cli/schemas/<command>-envelope.json
Der Fehler-Envelopeerror-envelope.json@verbatra/cli/schemas/error-envelope.json
Das Ergebnis von init allein, ohne Envelopeinit-result.json@verbatra/cli/schemas/init-result.json
Eine JSON-Zeile auf stderr: Fortschritt, Warten auf eine Sperre, Abbruchstderr-record.json@verbatra/cli/schemas/stderr-record.json
Die Konfigurationsdateiconfig.json@verbatra/sdk/schemas/config.json oder @verbatra/sdk/config-schema.json: dasselbe Schema ohne $id und title

Jede Befehlsseite verlinkt ihren Envelope unter JSON-Ausgabe, und https://verbatra.kreitz-webdev.de/schema/v1 listet jedes Dokument mit seinem Titel auf. Ein Befehls-Envelope verweist per URL in $ref auf das Schema seines result. Ein Validator lädt es also über das Netz, oder aus node_modules/@verbatra/sdk/dist/schemas, wenn du diese Dateien vorher registrierst.

v1 folgt Envelope version: 1 und liefert immer das neueste Release aus. Ein neues Feld bleibt in v1; eine Änderung, die eine Nutzlast bricht, erhöht die version des Envelopes und fügt /schema/v2/ hinzu. Das Konfigurationsschema nutzt dasselbe URL-Schema, folgt aber den Änderungen der Konfiguration selbst. Die URL liefert immer das neueste Release aus, eine Kopie aus npm bleibt bei ihrer Version. Eine ältere Kopie kann deshalb einen Datensatz einer neueren CLI ablehnen, wo ein Schema geschlossene Werte aufzählt, etwa den type eines stderr-Datensatzes oder den command eines Envelopes.

CLI-Fehlercodes Verfügbar ab 0.12.0

Diese Codes löst die CLI selbst aus. Dieselbe Liste wird als CLI_ERROR_CODES (mit dem Typ CliErrorCode) von @verbatra/cli ausgeliefert, sodass ein Skript einen Code dagegen prüfen kann. Jeder andere Code kommt vom SDK, einem Provider oder einem Format-Adapter. Was jeder Code bedeutet, welche Befehle ihn auslösen und was der nächste Schritt ist, steht unter Fehlercodes.

Fehler auf stderr

Jeder Fehler geht in beiden Modi als eine strukturierte Zeile (verbatra: error [CODE] message) auf stderr. Seit 0.12.0 gilt das auch für einen Fehler beim Parsen der Argumente (eine unbekannte Option oder ein unbekannter Befehl, ein fehlendes Argument): er gibt verbatra: error [USAGE_ERROR] unknown option '--nope' aus und endet mit 2, wo vorher commanders eigenes error: unknown option '--nope' ohne Code stand. init folgt derselben Grammatik seit 0.12.0; davor gab ein fehlender Provider verbatra: --provider is required (...) ohne Code aus. Seit 0.12.0 folgt ohne --json der Zeile ein Hinweis als next: ..., und mit --json schreibt ein Parse-Fehler den USAGE_ERROR-Envelope samt hint auf stdout; mcp hält stdout für das Protokoll frei und lehnt --json daher nur auf stderr ab. Der Start von studio und mcp ist die Ausnahme von der strukturierten Zeile: Ist @verbatra/studio oder @verbatra/mcp nicht installiert, steht auf stderr allein die Installationsanweisung, ohne das Präfix verbatra:. Mit --json ist die message eines Parse-Fehlers commanders eigener Text samt Präfix error: . Ohne --json schreibt ein fehlgeschlagener Lauf weiterhin überhaupt nichts auf stdout. Datensätze zu Fortschritt und Lock-Wartezeit gehen immer auf stderr, auf stdout stehen also ausschließlich Envelopes.

Terminalausgabe Verfügbar ab 0.12.0

Ergebnisse gehen auf stdout. Fortschritt, Hinweise, Tipps, Warnungen und Fehler gehen auf stderr, und verbatra passt sie daran an, wohin stderr geht:

  • In einem interaktiven Terminal sind feste Labels wie error, [ok] und next: eingefärbt, und ein Schritt, der länger als 300 ms dauert, zeigt einen ASCII-Spinner (| / - \).
  • Wenn stderr umgeleitet oder in eine Pipe geschrieben wird, CI auf einen anderen Wert als leer, 0 oder false gesetzt ist oder TERM den Wert dumb hat, besteht die Ausgabe aus schlichten, nur angehängten Zeilen ohne Farbe und ohne Animation.
  • Die Statuslabels des doctor-Berichts auf stdout ([ok ], [warn], [fail], [skip]) sind farbig, wenn stdout selbst ein interaktives Terminal ist; ein umgeleiteter Bericht bleibt schlicht, außer FORCE_COLOR schaltet die Farbe ein.
  • --json fügt nie Farbe oder Animation hinzu, und stdout trägt ausschließlich Envelopes. Schlichte verbatra:-Warnzeilen können trotzdem auf stderr landen, ein Konsument parst also nur die stderr-Zeilen, die mit { beginnen. Siehe JSON-Ausgabe.
Flag oder VariableWirkung
-q, --quietgibt nur Ergebnisse, Warnungen und Fehler aus: lässt Fortschrittszeilen, next:-Tipps und informative stderr-Zeilen weg, während die Ergebniszusammenfassung samt ihren Hinweisen bleibt. Es wirkt vor oder nach dem Befehlsnamen
--no-colorfärbt die Ausgabe nie ein
NO_COLOR, NODE_DISABLE_COLORS, VERBATRA_NO_COLORjeder nicht leere Wert schaltet die Farbe ab; VERBATRA_NO_COLOR übersteuert auch FORCE_COLOR
FORCE_COLOR1, 2, 3, true oder ein leerer Wert schaltet die Farbe ein, auch wenn stderr oder stdout kein Terminal ist, und jeder andere Wert, auch 0, schaltet sie ab. Ist es gesetzt, gewinnt es gegen NO_COLOR, NODE_DISABLE_COLORS, CI und TERM=dumb; --no-color und VERBATRA_NO_COLOR haben trotzdem Vorrang
VERBATRA_NO_SPINNERjeder nicht leere Wert ersetzt den Spinner durch statische Zeilen label... done (1.2s), für Screenreader und Terminalaufzeichnungen

Die output-Beispiele auf den Befehlsseiten zeigen die schlichte Form. Ein interaktives Terminal zeigt einen laufenden Schritt als Spinner-Zeile, die mit [ok] und der verstrichenen Zeit endet.

Statuswörter sind reines ASCII ([ok], [warn], [fail], [skip]), damit die Ausgabe in jedem Terminal und Log gleich lesbar ist. Jede Zeile durchläuft dieselbe Schlüsselschwärzung wie die übrige Ausgabe, und eingefärbt werden nur die festen Labels, nie ein Schlüssel, ein Pfad oder eine Meldung.

Auf GitHub bearbeiten

Auf dieser Seite