GrundkonzepteDie Lock-Datei

Die Lock-Datei

Was verbatra.lock.json festhält, wie Drift erkannt wird, wie parallele Läufe serialisiert werden und warum du die Datei committest.

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, verbatra.lock.json, existiert, damit ein Lauf erkennen kann, was schon übersetzt wurde, und es überspringt. Diese Datei ist die Baseline, mit der jeder Lauf vergleicht, und sie macht verbatra inkrementell. Diese Seite behandelt, was sie speichert, wie sie sich ändert und was passiert, wenn sie umkämpft, fehlend oder beschädigt ist.

Was sie festhält

Für jede Ziel-Locale speichert die Lock-Datei einen Content-Hash pro übersetztem Key, berechnet aus dem Quellwert, aus dem die bestehende Übersetzung entstanden ist. Die Datei enthält keine Übersetzungen und keine Geheimnisse: nur ein version-Feld und Hashes. Der Hash normalisiert Unicode zu NFC und Zeilenenden zu LF, sodass das erneute Speichern einer Quelldatei mit anderer Normalisierung oder mit CRLF-Enden nichts als geändert markiert.

Wie Drift erkannt wird

Wenn ein Lauf eine Ziel-Locale vergleicht, gilt ein Quell-Key, der im Ziel nicht vorkommt, als fehlend. Für einen Key, den das Ziel hat, wird der aktuelle Quell-Hash mit dem Hash verglichen, den die Lock-Datei aufgezeichnet hat: Ein Unterschied bedeutet, dass die Quelle seit der letzten Übersetzung des Keys gedriftet ist, er gilt also als geändert und wird neu übersetzt; eine Übereinstimmung bedeutet, dass er unverändert ist und nie an den Provider geht. Deshalb ruft ein zweiter Lauf ohne Quelländerungen den Provider für nichts auf, und deshalb können sich veraltete Übersetzungen nicht hinter einem Key verstecken, der bloß existiert. Die vollständige Pipeline steht auf Wie es funktioniert.

Ein bestehendes Projekt übernehmen

verbatra auf ein Repository zu richten, dessen Locale-Dateien schon geprüfte Übersetzungen enthalten, übersetzt diese nicht neu. Beim ersten Lauf gibt es keine Lock-Datei, also kann kein Key als veraltet erkannt werden: Ein Quell-Key, den die Zieldatei schon hat, gilt als unverändert, geht nie an den Provider und behält seinen bestehenden Wert. Nur Keys, die die Zieldatei nicht hat, sind fehlend, und nur die werden übersetzt. Wurde für eine Locale keine Übersetzung angenommen, kein Key entfernt und keine Form generiert, wird ihre bestehende Zieldatei gar nicht neu geschrieben.

Der Lauf hält trotzdem für jeden Key, den das Ziel enthält, den aktuellen Quell-Hash fest; der erste Lauf ist also der Übernahmeschritt selbst: Er legt die Baseline ohne einen einzigen Provider-Aufruf an, und ab dem zweiten Lauf tauchen Quelländerungen ganz normal als Drift auf.

Ob ein Key als übernommen gilt, entscheidet allein seine Anwesenheit, nie sein Wert. Daraus folgen zwei Dinge, die du vor diesem ersten Lauf kennen solltest:

  • Ein leerer oder unübersetzter Wert zählt als übersetzt. Ein Zielwert, der ein leerer String ist oder noch der unübersetzte Quelltext, ist ein Key, der existiert, gilt also als unverändert und wird nie gefüllt. Scaffolding-Tools, die Locale-Dateien mit leeren Strings vorab anlegen, laufen genau da hinein. Die Lösung ist, den Key aus der Zieldatei zu löschen: den Wert zu leeren hilft nicht, denn ein leerer String ist weiterhin ein Eintrag. Ist der Key weg, sieht ihn der nächste Lauf als fehlend und übersetzt ihn.
  • Eine schon vorher veraltete Übersetzung wird als aktuell verbucht. Die Lock-Datei nimmt den Quell-Hash so, wie er jetzt ist; eine Übersetzung, die schon vor der Übernahme von der Quelle abgedriftet war, gilt damit als aktuell und wird nicht noch einmal angefasst. Korrigiere oder lösche solche Keys vor dem ersten Lauf.

Die Plural-Generierung folgt derselben Übernahmeregel. Eine Pluralform, die die Zieldatei schon enthält und die verbatra nicht selbst generiert hat, bleibt so, wie sie ist: Sie wird weder neu generiert noch an den Provider geschickt (eine Form, die die Lock-Datei bereits führt, wird sehr wohl neu generiert, sobald sich ihre Quelle ändert). generatePlurals kannst du also gefahrlos anlassen, während du ein Projekt mit handgeschriebenen Pluralformen übernimmst; synthetisiert werden nur Formen, die im Ziel wirklich fehlen.

Das alles kannst du dir ansehen, bevor du etwas ausgibst: verbatra diff listet pro Locale genau die fehlenden und geänderten Keys, verbatra check meldet dasselbe als Zahlen, und verbatra translate --dry-run gibt dir die vollständige Lauf-Zusammenfassung. Keiner der drei ruft einen Provider auf, schreibt eine Locale-Datei oder schreibt die Lock-Datei.

Wie sie aktualisiert wird

Die Lock-Datei wird pro Locale aktualisiert, und wie, hängt davon ab, was gelaufen ist:

  • Ein vollständiger Lauf (translate, watch oder ein Arbeitsmappen-Import) ersetzt die Einträge dieser Locale im Ganzen durch das maßgebliche Ergebnis des Laufs.
  • Eine Einzel-Key-Aktion (etwa ein Retranslate aus Studio) mergt nur den Eintrag dieses Keys und lässt jeden anderen aufgezeichneten Key unangetastet.

In beiden Fällen gilt eine Ausnahme: Ein in diesem Lauf zurückgehaltener Key (eine fehlgeschlagene Integritätsprüfung, ein fehlgeschlagener Provider-Aufruf oder eine Quelle mit ungültigem ICU) behält seinen vorherigen Hash, damit der nächste Lauf ihn weiterhin als arbeitsbedürftig sieht und erneut versucht, statt ihn als erledigt zu verbuchen. Verwaiste Keys bekommen keinen Eintrag. Die Datei wird mit sortierten Keys serialisiert, damit ihre Diffs stabil und gut zu reviewen bleiben.

Die Schreibsperre

Zwei Läufe, die gleichzeitig dieselbe Locale anfassen (ein zweites Terminal, ein CI-Job, eine Studio-Aktion), könnten sonst beide mit einer veralteten Baseline vergleichen und beide denselben Provider-Aufruf bezahlen. Um das zu verhindern, passiert jeder Schreibvorgang an einer Locale und ihren Lock-Einträgen unter einer prozessübergreifenden Schreibsperre für genau diese eine Locale; ein zweiter Schreiber für dieselbe Locale wartet, liest die Lock-Datei dann frisch neu ein und vergleicht mit einer Baseline, die das Ergebnis des ersten Schreibers schon enthält. Verschiedene Locales blockieren einander nicht.

Übersetzt ein Lauf mehrere Locales gleichzeitig und trifft auf einen Fehler des gesamten Laufs (in der Praxis eine beschädigte Lock-Datei), beansprucht er keine neuen Locales mehr und wartet, bis die bereits laufenden fertig sind; so wird jede Sperre, die der Lauf genommen hat, freigegeben, bevor der Befehl endet. Nach dem Fehlschlag des Laufs wird kein Locale mehr gestartet, und der Fehlschlag selbst lässt keine Sperre verwaist zurück.

Kann eine Sperre nicht erworben werden, schlägt der Lauf mit LOCK_CONTENDED fehl und nennt den Pfad der Sperrdatei (im gitignorierten Verzeichnis .verbatra-local/). Läuft gerade kein verbatra-Prozess, wurde diese Datei von einem abgeschossenen Prozess zurückgelassen: Lösche sie und versuche es erneut.

Fehlend oder beschädigt

Eine fehlende Lock-Datei ist kein Fehler: Es ist ein erster Lauf, und ohne Baseline kann nichts als veraltet erkannt werden. Quell-Keys, die die Zieldatei nicht hat, sind fehlend und werden übersetzt; Keys, die sie hat, gelten als unverändert und bleiben unangetastet, wie oben bei der Übernahme beschrieben. Eine Lock-Datei, die vorhanden, aber nicht parsebar, strukturell falsch, zu groß oder auf einer nicht unterstützten Version ist, lässt den Lauf mit LOCK_FILE_INVALID fehlschlagen, statt still überschrieben zu werden, damit du sie untersuchen oder wiederherstellen kannst, statt die Baseline zu verlieren.

Committe sie

Committe verbatra.lock.json zusammen mit deinen Locale-Dateien. Diese Datei ist die gemeinsame Baseline, mit der deine Teamkollegen und deine CI vergleichen; sie in der Versionskontrolle zu halten macht inkrementelle Läufe über Maschinen hinweg reproduzierbar. Bearbeite sie nie von Hand.

Beide zu committen ist auch das, was ein Rollback möglich macht. Weil die Lock-Datei Quell-Hashes festhält und nichts über die übersetzten Werte, behauptet sie nach einem Zurücksetzen deiner Locale-Dateien ohne sie weiterhin, die zurückgesetzten Übersetzungen seien aktuell, und nichts übersetzt sie neu. Siehe Wiederherstellung und Rollback.

Edit on GitHub