Zum Inhalt springen
Zum Inhalt springen

Docs / Konzepte

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.

Die Lock-Datei und die Herkunft

Was verbatra.lock.json und verbatra.provenance.json festhalten, wie Drift erkannt wird, wie parallele Läufe serialisiert werden und warum du beide committest.

verbatra.lock.json ist die Baseline, gegen die jeder Lauf vergleicht, sodass ein Lauf Aktuelles überspringen und Abgedriftetes neu übersetzen kann. Daneben hält verbatra.provenance.json fest, wer oder was jeden Wert geschrieben hat.

Was sie festhält

Für jede Ziel-Locale einen Hash pro übersetztem Key, gebildet aus dem Quelleintrag hinter der aktuellen Übersetzung, plus ein Feld version: keine Übersetzungen, keine Secrets. Der Hash deckt den Quellwert samt Beschreibung, Bedeutung, Plural-Flag und Platzhaltern ab, eine geänderte Beschreibung macht den Key also ebenfalls veraltet. Er normalisiert Unicode auf NFC und Zeilenenden auf LF, ein erneutes Speichern einer Quelldatei mit CRLF-Zeilenenden ändert also nichts.

Wie Drift erkannt wird

Ein Quell-Key, der im Ziel fehlt, ist missing. Bei einem vorhandenen Key wird der aktuelle Quell-Hash mit dem festgehaltenen verglichen: Ein Unterschied heißt, die Quelle hat sich geändert und der Key wird neu übersetzt; eine Übereinstimmung heißt, er wird nie gesendet, ein zweiter Lauf ohne Änderungen an der Quelle kostet also nichts. Die ganze Pipeline steht unter Wie ein Lauf funktioniert.

Geschützte Keys

Die Ausnahme ist ein geänderter Key, dessen Wert ein Mensch geschrieben oder importiert hat: Er ist standardmäßig geschützt und bleibt veraltet, statt neu übersetzt zu werden.

Ein bestehendes Projekt übernehmen

Locale-Dateien, die schon reviewte Übersetzungen enthalten, werden nicht neu übersetzt. Beim ersten Lauf gibt es keine Lock-Datei, also kann nichts veraltet sein: Ein Key, den das Ziel hat, behält seinen Wert, nur fehlende Keys werden übersetzt, und der Lauf hält jeden Quell-Hash als Baseline fest, ohne Provider-Kosten.

Die Übernahme richtet sich nach dem Vorhandensein eines Keys, nie nach seinem Wert, und das hat zwei Folgen:

  • Ein leerer oder unübersetzter Wert zählt als übersetzt. Lösch den Key (ihn zu leeren reicht nicht), und der nächste Lauf übersetzt ihn.
  • Eine veraltete Übersetzung wird als aktuell festgehalten. Korrigiere oder lösch sie vor dem ersten Lauf.

Dieselbe Regel behält handgeschriebene Pluralformen bei, generatePlurals ist bei der Übernahme also sicher. Um all das vorab zu sehen, führ verbatra diff oder verbatra translate --dry-run aus.

Wie sie aktualisiert wird

  • Ein vollständiger Lauf (translate, watch oder ein Import) ersetzt die Einträge einer Locale durch das Ergebnis des Laufs.
  • Eine Aktion für einen einzelnen Key, etwa ein Retranslate aus Studio, mergt nur den Eintrag dieses Keys.

In beiden Fällen behält ein Key, der in diesem Lauf zurückgehalten wurde (eine gescheiterte Integritätsprüfung oder ein gescheiterter Provider-Aufruf, eine Quelle mit ungültigem ICU), seinen bisherigen Hash, sodass der nächste Lauf ihn erneut versucht. Verwaiste Keys bekommen keinen Eintrag, und sortierte Keys halten die Diffs klein.

Die Schreibsperre

Zwei Läufe, die gleichzeitig dieselbe Locale anfassen, könnten beide gegen eine veraltete Baseline vergleichen und doppelt bezahlen, deshalb hält jeder Schreibvorgang eine prozessübergreifende Sperre für diese Locale unter .verbatra-local/. Ein zweiter Schreiber wartet und vergleicht dann gegen eine Baseline, die das Ergebnis des ersten enthält. Verschiedene Locales blockieren sich nie gegenseitig.

Was die Sperre garantiert:

  • Ein Timeout kostet nichts. --lock-timeout begrenzt nur das Warten vor jedem Provider-Aufruf, eine Locale, die aufgibt, hat also nichts ausgegeben und nichts geschrieben; das Festhalten einer geschriebenen Datei wartet die vollen zehn Minuten des Standards.
  • Verwaiste Sperren blockieren dich nicht. Eine Sperre, deren Prozess auf diesem Rechner nicht mehr existiert, wird sofort übernommen, und eine, die 30 Sekunden lang nicht aufgefrischt wurde (Halter frischen alle 10 auf), gilt als verwaist.
  • Ein Abbruch gibt die Sperren frei. Ctrl-C oder SIGTERM während translate oder import und der zweite Abbruch, der watch zwangsweise beendet, geben jede Sperre frei, bevor der Prozess endet.
  • Eine verlorene Sperre stoppt den Schreibvorgang. Jede Sperre trägt ein zufälliges Token, das vor jedem Schreibvorgang geprüft wird; hat ein anderer Lauf die Sperre übernommen, stoppt der Schreibvorgang mit LOCK_CONTENDED, und nichts wird geschrieben.

Was sie nicht abdeckt:

  • Eine Sperre von einem anderen Rechner (ein geteiltes Netzlaufwerk) oder von einer verbatra-Version vor 0.12.0 wird nie automatisch übernommen; wie du sie entfernst, steht unter Fehlerbehebung.
  • Eine lange Pause zwischen Prüfung und Schreiben. Ein Lauf, der direkt nach der Token-Prüfung pausiert (ein schlafender Rechner, ein angehaltener Prozess), kann nach dem Fortsetzen noch einmal schreiben.
  • Hosts mit gleichem Namen. Außerhalb von Linux ist der Hostname die einzige Rechneridentität, zwei Container mit einem Hostnamen, die sich .verbatra-local/ teilen, können also die lebende Sperre des anderen für verwaist halten. Gib jedem seinen eigenen Hostnamen oder seine eigene Arbeitskopie.

Ein umgeschriebener Locale-Code

Die Lock-Datei, der Cache und die Herkunftsdatei ordnen ihren Zustand nach dem Locale-Code deiner Konfiguration. Schreibst du einen um, etwa pt_BR zu pt-BR, überträgt der nächste Lauf von translate oder watch den alten Zustand einmalig und meldet LOCALE_STATE_CARRIED_OVER. Eine Quelländerung vor der Umbenennung wird trotzdem neu übersetzt, und gecachte Übersetzungen werden weiter wiederverwendet.

Die Übertragung passiert nur, wenn eindeutig: pt-BR hat keinen eigenen Zustand, und die Datei hält Zustand unter genau einer Unterstrich-Schreibweise davon (oder seiner gettext-Schreibweise, etwa sr@latin für sr-Latn), ohne Beachtung der Groß- und Kleinschreibung. Zustand, den pt-BR schon hat, wird nie überschrieben. Lässt sich die Übertragung nicht schreiben, läuft diese Locale nicht und scheitert mit LOCALE_STATE_NOT_CARRIED_OVER, sodass der nächste Lauf es erneut versucht; die anderen Locales laufen wie gewohnt.

Bis dahin behandelt jedes Lesen den alten Zustand als den von pt-BR, ohne zu schreiben, ein veralteter Key wird also als veraltet gemeldet. Ein Schreibvorgang für einen einzelnen Key (eine Bearbeitung, ein Retranslate, eine Review-Entscheidung) und verbatra import übertragen den Zustand vorher auf dieselbe Weise. Die Prüfung locale-state von verbatra doctor nennt zurückgebliebenen Zustand.

Fehlend oder beschädigt

Eine fehlende Lock-Datei ist ein erster Lauf, kein Fehler. Eine, die sich nicht parsen lässt, strukturell falsch, zu groß oder in einer nicht unterstützten Version ist, lässt den Lauf mit LOCK_FILE_INVALID scheitern, statt überschrieben zu werden, sodass du sie wiederherstellen kannst, statt die Baseline zu verlieren.

Herkunft: wer welchen Wert geschrieben hat

verbatra.provenance.json hält fest, welcher Schreibpfad jeden Wert erzeugt hat, der jetzt in der Locale-Datei steht, und ob ihn jemand reviewt hat. Eine ältere verbatra-Version, etwa eine in CI gepinnte, ignoriert sie.

HerkunftGeschrieben von
machineeiner Provider-Antwort in translate, watch oder einem Retranslate eines einzelnen Keys, mit der id des Providers und, wenn bekannt, dem Modell
memoryeinem exakten Cache-Treffer, einschließlich jedes Werts, den ein reiner Handarbeits-Lauf (Provider none) füllt
fuzzyeinem Treffer der unscharfen Wiederverwendung
humander Bearbeitung eines Menschen über editEntry aus dem SDK, wie sie der Bearbeitungsdialog in Studio macht
agentder Bearbeitung eines KI-Agenten über editEntry mit actor: "agent"
importeiner angenommenen Zeile aus verbatra import
unknowneiner Review-Entscheidung zu einem Wert ohne Eintrag, oder einer Herkunft, die dieses Release nicht kennt

Zwei weitere werden beim Lesen abgeleitet: unrecorded ist ein Wert ohne Eintrag, wie jeder Key nach einem Upgrade; external passt nicht mehr zum Hash seines Eintrags, weil ihn etwas außerhalb von verbatra geändert hat, etwa der Pull Request eines Übersetzers, ein älteres verbatra oder ein Merge. Die Felder, die jedes Lesen liefert, stehen in der SDK-Referenz.

Was die Datei garantiert:

  • Stabile Diffs. Kein übersetzter Text und keine Zeitstempel, ein sortierter Eintrag pro Zeile, ein Lauf, der nichts ändert, lässt die Datei also unverändert. Bei einem Merge-Konflikt nimm die Seite, die zur behaltenen Locale-Datei passt: Ein abweichender Eintrag liest sich als external, was den Wert vor Neuübersetzung schützt.
  • Frische Einträge für neue Werte. Ein Schreibvorgang, der einen Wert ändert, ersetzt seinen Eintrag durch einen neuen, nicht reviewten; einer, der Wert und Quelle unverändert lässt, behält ihn.
  • Kein stilles Überschreiben. Eine beschädigte Datei stoppt jeden Schreibvorgang mit PROVENANCE_FILE_INVALID, bevor sich eine Locale-Datei ändert; Berichte lassen ihre Herkunftsfelder stattdessen weg. Eine Datei von einer neueren verbatra-Version bleibt unangetastet, und eine, die zu groß zum Zurücklesen würde, wird nicht geschrieben (PROVENANCE_FILE_TOO_LARGE).

Sie ist nicht fälschungssicher; um daraus einen Bericht zu machen, siehe Nachweis maschineller Übersetzungen festhalten.

Review-Entscheidungen

Ein Eintrag kann eine Review-Entscheidung tragen, approved oder rejected, mit einem optionalen Namen unter reviewer. Studios Review-Seite, die Review-Funktionen des SDK und die MCP-Review-Tools schreiben sie; die MCP-Tools geben die Entscheidung eines Menschen weiter und verlangen dessen Namen. Eine Entscheidung gilt für genau den Wert, den der Reviewer gesehen hat, und wird abgelehnt, wenn er sich geändert hat.

  • Eine Freigabe ändert nur die Herkunftsdatei und liest sich wieder als nicht reviewt, sobald sich der Quelltext ändert.
  • Eine Ablehnung entfernt den Wert und seinen Lock-Eintrag, sodass der Key als missing gilt, bis der nächste Lauf von translate oder ein Mensch einen neuen Wert schreibt. Der Eintrag behält einen Hash des entfernten Texts und der Cache-Eintrag wird verworfen, damit ein Lauf nicht denselben Text zurückbringt. XLIFF kann keine einzelne Übersetzung weglassen, eine Ablehnung wird dort also mit REVIEW_REJECT_UNSUPPORTED abgelehnt.

Nur Werte der Maschinenklasse landen in der Review-Warteschlange und im --require-reviewed-Gate. Die byReviewState-Zähler in check und lock.state erfassen jeden Wert nach seiner aufgezeichneten Entscheidung, gleich welcher Herkunft: Ein von einer Person geschriebener oder importierter Wert ohne Entscheidung zählt dort als unreviewed, ohne in der Warteschlange zu stehen. Lies sie zusammen mit byOrigin.

Die Entscheidungen stehen in dieser committeten Datei, also sehen die Review-Warteschlange und verbatra check --require-reviewed auf jedem Rechner denselben Zustand, und der Name unter reviewer ist öffentlich; verbatra trägt ihn nie ein.

Committe sie

Committe verbatra.lock.json und verbatra.provenance.json mit deinen Locale-Dateien und bearbeite sie nie von Hand: sie sind die Baseline, gegen die dein Team und deine CI vergleichen, und das, was ein Rollback wiederherstellt.

Auf GitHub bearbeiten

Auf dieser Seite