Referenz / Konfiguration
Maschinell übersetzte Seite
Formate
Alle i18n-Dateiformate, die verbatra unterstützt, wie jedes seine Dateien liest und schreibt und was ein Schreibvorgang erhält, damit Diffs sauber bleiben.
Ein Format-Adapter liest eine Locale-Datei in eine neutrale Form und schreibt sie in der eigenen Form der Datei zurück. Setze den format-Key deiner Konfiguration auf eine dieser Ids:
format | Dateien | Platzhalter | Plurale | Fehlende Zieldatei | Native Platzhaltersyntax |
|---|---|---|---|---|---|
i18next-json | i18next-JSON (.json) | {{name}}, $t(...) | CLDR-Suffix am Key | angelegt | {{name}} |
vue-i18n-json | vue-i18n-JSON (.json) | {name}, {0} | Pipe im Wert | angelegt | {name}, %{name}, ${name} |
next-intl-json | next-intl-JSON (.json) | ICU-Argumente und -Tags | ICU plural, selectordinal | angelegt | {name}, %{name}, ${name} |
ngx-translate-json | ngx-translate-JSON (.json) | {{name}} | keine | angelegt | {{name}} |
xliff | XLIFF 1.2 und 2.0 (.xlf, .xliff) | Inline-Elemente, {...} | keine | abgelehnt | {{name}}, {name}, %{name}, ${name} |
yaml | YAML (.yml, .yaml) | {{name}} | keine | angelegt | {{name}} |
arb | Flutter-ARB (.arb) | ICU-Argumente und -Tags | ICU plural, selectordinal | angelegt | {name}, %{name}, ${name} |
properties | Java/Spring-Properties (.properties) | MessageFormat {0}, {count} | keine | angelegt | {name}, %{name}, ${name} |
apple-strings | Apple-.strings, mit der zugehörigen .stringsdict | printf %@, %d | .stringsdict-Kategorien | angelegt | printf %s |
apple-xcstrings | Xcode String Catalogs (.xcstrings) | printf %@, %lld | variations.plural | abgelehnt | printf %s |
android-xml | Android strings.xml | printf %s, %1$s | <plurals>-Quantitäten | angelegt | printf %s |
gettext-po | gettext (.po, .pot) | printf, %(name)s | msgstr[n] | angelegt | printf %s, %(name)s |
ini | INI (.ini) | {name}, {0} | keine | angelegt | {name}, %{name}, ${name} |
resx | .NET-Ressourcen (.resx) | Composite {0}, {1:C}, benannt {name} | keine | angelegt | {{name}}, {name}, %{name}, ${name} |
Wähle das Format passend zu deiner i18n-Bibliothek: Es entscheidet, welche Platzhalter die Integritätsprüfung vergleicht.
Die vier JSON-Formate
Alle vier lesen verschachtelte JSON-Objekte mit String-Blättern.
i18next-json
{{double-brace}}-Interpolation; der Plural kommt aus dem CLDR-Suffix am Key (_, _, _, _, _, _). Die Verschachtelungsreferenzen $t(common.foo) und $t(common.foo, { options }) werden als Platzhalter geschützt; nur das Standard-Präfix $t( zählt, ohne verschachtelte Klammern in den Optionen.
vue-i18n-json
Einzelklammer-Tokens {name} und {0}, Namen in jeder Schrift ({número}). Der Plural kommt aus einer Pipe im Wert.
next-intl-json
Werte sind ICU MessageFormat: Die Namen von Argumenten und Rich-Text-Tags sind die Platzhalter, und der ICU-Körper wird wortgetreu erhalten, nur bekommt jedes plural und selectordinal die CLDR-Zweige der Zielsprache. Ein Wert, der nicht als ICU parst, wird als ungültig gemeldet und übersprungen.
ngx-translate-json
{{double-brace}}-Interpolation, keine Verschachtelungsreferenzen, keine Plurale und kein ICU. Eine Datei darf flach (gepunktete Keys) oder verschachtelt sein, und jede behält ihren Stil beim Schreiben; ein neues Ziel wird verschachtelt geschrieben. Eine Datei, die beides mischt, scheitert mit MIXED_.
Die Erfindungs-Schranke für Einzelklammern
Unter i18next-json, ngx-translate-json und yaml ist ein {name}-Token Literaltext, den eine Übersetzung umformulieren darf, aber eines, das in der Quelle nie vorkam, wird als Erfindung abgelehnt. Nur diese Richtung ist geschützt: Mit eigenen Einzelklammer-Werten für interpolation.prefix und suffix wird ein weggelassener Platzhalter nicht erkannt.
Namespace-Layouts
files.pattern ist ein wörtlicher Pfad, nie ein Glob: public/locales/{locale}/*.json sucht eine Datei mit dem Namen *.json und scheitert mit SOURCE_. Ein einzelner Namespace funktioniert wie konfiguriert:
files: {
pattern: "public/locales/{locale}/common.json",
},Eine Konfiguration pro Namespace
Schreib für mehrere Namespaces je eine Konfiguration und führe sie nacheinander aus:
verbatra translate --config verbatra.common.config.ts
verbatra translate --config verbatra.auth.config.tsNur der zuletzt gelaufene Namespace behält die Änderungserkennung
Alle Konfigurationen in einem Verzeichnis teilen sich verbatra.lock.json, und jeder Lauf ersetzt die Baselines der Locale durch seine eigenen Keys, ein bearbeiteter String eines früheren Namespace gilt also als synchron und wird nicht neu übersetzt. Um ihn neu zu übersetzen, lösche den Key (oder die Zieldatei), damit er als fehlend zählt.
XLIFF
XLIFF 1.2 (file/body/trans-unit) und 2.0 (file/unit/segment), eine flache Liste von Units.
- Keys. Die
idder Unit, dannresname, dann eine Position, die sich verschiebt, wenn Units wandern; gib also jeder Unit eineid. Eine 2.0-Unit mit mehreren Segmenten bekommt Keys der Form<id>#<n>. Ein doppelter Key scheitert mitINVALID_.STRUCTURE - Quelle oder Übersetzung. Ein Dokument ist die Quelle, wenn die Locale zu seiner
source-languagepasst (srcLangin 2.0; eine reine Sprache passt zu ihren regionalen Formen) und es diese Locale nicht als Ziel deklariert; alles andere ist eine Übersetzung, außer ein Dokument, das keine der beiden Sprachen deklariert: Es ist die Quelle, wenn es kein<target>enthält. Ein Ziel mit derselben Sprache wie die Quelle (enzuen-GB) musstarget-language(trgLang) deklarieren. - Fehlende Werte. Ein
<target>, das fehlt, leer ist oder in 1.2 mitstate="new"oder"needs-translation"markiert ist, gilt als fehlend, ebenso ein 2.0-Target, das seiner Quelle gleicht, in einem Segment mitstate="initial". Der<source>-Text wird nie hineinkopiert. - Schreiben an Ort und Stelle. Jeder Wert geht in sein
<target>, das nach<source>angelegt wird, wenn es fehlt, und ein 1.2-Statenewoderneeds-translationoder ein 2.0-Stateinitial(samtsubState) wird zutranslated.<source>, Attribute und<note>bleiben unangetastet. - Fehlende Units werden ergänzt als Kopie der Quell-Unit (ohne ihre Targets und das 1.2-
<alt-trans>) im passenden<file>. Ein Wert ohne Unit, in die er gehen kann, lässt das Schreiben mitINVALID_scheitern und nennt den Key; eine unlesbare Quelle lässt es ohne Key scheitern.STRUCTURE verbatra extracthängt Quell-Units nur mit<source>an; in 2.0 muss der Key ein gültiges NMTOKEN sein (u1#0wird abgelehnt). - Inline-Markup. Die 1.2-Elemente
g,x,bx,ex,bpt,ept,ph,it,mrk, die 2.0-Elementeph,pc,sc,ec,mrk,sm,em,cpund jede{...}-Folge sind in beiden Versionen geschützte Platzhalter. Beim Schreiben bleiben nur diese (plus das 1.2-<sub>innerhalb vonbpt,ept,ph,it) Markup; alles andere, etwa<b>, wird zu Text. - Escaping. Text wird als Text gelesen (
A & BistA & B) und beim Schreiben einmal escaped; Text, der genau einem erlaubten Element entspricht, etwa<x id="1"/>, wird als dieses Element geschrieben,<!DOCTYPEund<!ENTITYals Text. - Notes (in 2.0 die
<notes>der Unit) sind nur lesbarer Kontext. - Abgelehnte Eingabe. Ein Dokument mit einer DTD- oder Entity-Deklaration scheitert mit
INVALID_.XML
YAML
Ein verschachtelter Baum wie bei den JSON-Formaten, mit i18nexts {{double-brace}}-Interpolation und der Erfindungs-Schranke, erkannt an der Endung. Kommentare bleiben nicht erhalten. Skalare Nicht-String-Keys werden zu Strings (1: wird als "1" gelesen), eine Map oder Sequenz als Key scheitert mit INVALID_, fehlerhafte Syntax scheitert mit INVALID_, und die Alias-Expansion ist begrenzt.
ARB
Flutters .arb: ein flaches Objekt aus Nachrichten mit @key-Metadaten und @@-Globals.
- Nachrichten sind ICU und werden genau wie bei
next-intl-jsonbehandelt. - Metadaten werden nie übersetzt und an ihrer Position wieder eingefügt; ein beschädigtes vorhandenes Ziel lässt das Schreiben scheitern.
@key.descriptionist nur lesbarer Kontext. - Ein Schreibvorgang enthält genau seine Nachrichten. Eine ausgelassene Nachricht (entfernt per Prune oder im Review abgelehnt) fällt samt ihrem
@key-Block weg;@@-Globals bleiben. @@localesteht vorne. Ein neu angelegtes Ziel beginnt damit, in der Schreibweise vongen-l10n(pt_); ein vorhandenes behält seinen Wert und wandert nach oben, hinzugefügt wird es nie. Korrigiere einen Wert, der nicht zum Dateinamen passt, von Hand, sonst scheitertBR flutter gen-l10n.
Properties
Javas und Springs .properties: flache Key/Wert-Zeilen, Keys wortgetreu erhalten.
- Die Syntax folgt
java.util.Properties(Trennzeichen, Kommentare, Fortsetzungszeilen, Escapes). Dateien werden als UTF-8 gelesen, und Nicht-ASCII wird als\uXXXXgeschrieben. - Schreibvorgänge erhalten Key-Reihenfolge, Kommentare und Leerzeilen, schreiben jede vorhandene Zeile an Ort und Stelle neu und hängen neue Keys in Quellreihenfolge an. Ein doppelter Key behält seine erste Position und seinen letzten Wert.
- Zeilenenden folgen der Datei: irgendein CRLF heißt überall CRLF, reines CR bleibt CR, sonst LF.
- Platzhalter sind
java.text.MessageFormat:{0},{0,number},{count}(Namen in jeder Schrift) sowie Argumente vom Typplural,select,selectordinalundchoice. Die Maskierung mit einfachen Anführungszeichen wird nicht interpretiert,'{0}'zählt also weiterhin als Platzhalter.
Apple .strings
"key" = "value";-Anweisungen, mit Pluralen in der zugehörigen .stringsdict (gleiches Verzeichnis, gleicher Basisname), die zusammen gelesen und geschrieben werden.
- Nur UTF-8. Eine UTF-16-Datei scheitert mit
INVALID_; speichere sie neu als UTF-8.STRUCTURE - Kommentare. Ein
/* ... */-Kommentar vor einem Eintrag ist nur lesbarer Kontext;//-Kommentare bleiben erhalten. Die Escapes\",\\,\n,\tund\Uwerden dekodiert; beim Schreiben werden nur Anführungszeichen, Backslash, Zeilenumbruch und Tabulator maskiert. - Schreibvorgänge erhalten Reihenfolge, Kommentare und Leerzeilen; ein entfernter Key geht samt seinem eigenen Kommentar. Ein fehlendes Ziel wird angelegt,
.lproj-Verzeichnis und.stringsdicteingeschlossen. - Platzhalter sind printf:
%@,%d,%1$@,%%, mit Flags, Breite und Länge als Dekoration; ein positionelles Umstellen wird akzeptiert. Ein einzelnes%("50% off") ist keiner. - Plurale. Jede
.stringsdict-Kategorie wird zu<key>_(<category> photo_), und nur die Kategorien, die eine Locale hat, überstehen den Roundtrip. Fehler nennen Datei und Key; Format-Key, Variablenname und Werttyp überstehen einen Neuschrieb.count_ one - Layout.
{locale}.lproj/Localizable.stringsbraucht keinen besonderen Locale-Style.
Xcode String Catalogs (.xcstrings)
Ein JSON-Katalog, der jede Locale enthält, der Ersatz für .strings seit Xcode 15.
- Eine Datei für alle Locales.
files.patternbraucht weiterhin{locale}, aber{locale}wird zu einem leeren String, sodass sich jede Locale zur selben Datei auflöst ({locale}Localizable.xcstringsergibtLocalizable.xcstrings). Jeder Schreiber wird darauf serialisiert, Locales laufen also auch mit--concurrencynacheinander. - Keys. Ein Key ohne
sourceLanguage-Localization verwendet den Key-Text als Quelle; eine fehlende Ziel-Localization zählt als nicht übersetzt. - Plurale unter
variations.pluralwerden zu<key>_, nur für die vorhandenen Kategorien.<category> - Platzhalter sind printf, wie bei
.strings;%lldist gleich%d. shouldTranslate: false-Keys werden nie gesendet oder geändert.- Schreibvorgänge patchen das Dokument. Nur berührte Localizations ändern sich, ein neuer Wert bekommt
state: "translated", und der Rest bleibt semantisch identisch, auch wenn die Datei als JSON mit 2 Leerzeichen Einrückung neu serialisiert wird. Leg den Katalog zuerst in Xcode an. - Fehler nennen die Datei und, innerhalb eines Eintrags, Key und Locale.
Android strings.xml
res/values/strings.xml für die Quelle und res/values-<qualifier>/strings.xml pro Ziel; setze files.localeStyle: "android" (Konfiguration).
- Einträge.
<string name>ist ein Eintrag;<plurals>wird pro<item>zukey[quantity], nur für die vorhandenen Quantitäten. - Übersprungen. Ressourcen mit
translatable="false",<string-array>und ein<string>mit Inline-Elementen (<b>,<xliff:g>, CDATA) bleiben, wie sie sind;formatted="false"wird normal übersetzt. - Escaping.
\',\",\n,\tund ein führendes\@oder\?werden dekodiert und beim Schreiben wieder maskiert. - Platzhalter sind printf:
%s,%d,%1$s,%%; ein einzelnes%ist keiner. - Schreibvorgänge patchen die Datei, löschen entfernte Keys und legen eine fehlende Datei samt Verzeichnis an.
- Grenzen. Ein übersetzter Key, der in der Quelle später zum Durchreichen wird, wird aus dem Ziel entfernt.
--pruneweiß nichts von Plural-Quantitäten und kann deshalb Quantitäten löschen, die nur im Ziel vorkommen. - Fehler nennen ein Wurzelelement außer
<resources>, einen ungültigen Namen oder eine ungültige Quantität oder einen doppelten Key; eine DTD oder Entity wird abgelehnt.
gettext .po/.pot
msgid/msgstr-Einträge mit der msgid als Key.
msgctxtwird mit U+E000 an seinemsgidzu einem Key gefügt; eine Quelle, die dieses Zeichen enthält, wird abgelehnt.- Plurale werden über den Index adressiert,
key[n], nicht über die CLDR-Kategorie.Plural-Formsbleibt wörtlich erhalten, und nur seinnpluralsbegrenzt die Indizes; Plural-Einträge ohne ihn werden abgelehnt, wie esmsgfmt --checktut. - Flags und Kommentare. Ein
#, fuzzy-Wert wird als aktuell gelesen und das Flag erhalten.#.-Kommentare sind nur lesbarer Kontext;#:und andere Flags bleiben erhalten,#~-Blöcke bleiben inert, und der Header wird nie angefasst. Eine.potmit leeremmsgstrwird sauber gelesen, aber in einem Quellkatalog ist jedermsgstrder zu übersetzende Text, ein leerer wird also mitSOURCE_übersprungen.VALUE_ EMPTY - Ein fehlendes Ziel wird mit einem minimalen Header angelegt und, bei Pluralen, mit einem
Plural-Forms, das auf den höchsten Index zugeschnitten ist (für die exakte Grammatik leg das Ziel aus einer echten Vorlage an). - Platzhalter sind printf,
%(name)seingeschlossen. - Fehler nennen die
msgidund die Zeile.--pruneweiß nichts von Plural-Indizes und kann deshalb Formen löschen, die nur im Ziel vorkommen.
INI
Eine Ebene von [section]-Headern über key=value-Zeilen.
- Keys. Ein Key in
[home]isthome.title; Keys oberhalb der ersten Section behalten ihren blanken Namen, und wörtliche Punkte werden maskiert. - Schreibvorgänge ändern nur Werte und erhalten Schreibweise, Abstände, Kommentare und Leerzeilen. Ein neuer Key kommt ans Ende seiner Section, eine neue Section ans Ende der Datei.
- Werte. Werte in doppelten Anführungszeichen werden entpackt, wobei
\\,\",\n,\r,\tdekodiert werden, und ein Wert, der es braucht, wird in Anführungszeichen geschrieben. Ein;mitten in der Zeile gehört zum Wert. - Platzhalter sind
{name}und{0}, Namen in jeder Schrift; keine Plurale. - Fehler. Ein fehlerhafter Header löst einen
AdapterErroraus; eine Zeile ohne=bleibt wörtlich erhalten.
.NET .resx
<data name><value>-Elemente unter <root>, nur für .resx beansprucht.
- Schreibvorgänge patchen nur Werte: Alles andere kommt unverändert zurück, auf dem Zeilenende der Datei; ein Byte-Order-Mark fällt weg, und ein neues
<data>-Element oder eines, dessen Wert Leerraum am Rand hat, bekommtxml:space="preserve". - Nicht übersetzt.
<data>mittypeodermimetypeund Namen, die mit>>oder$beginnen, bleiben, wie sie sind. Ein<comment>ist nur lesbarer Kontext. - Platzhalter sind Composite-Format-Items und benannte Platzhalter, vollständig erfasst (
{0},{1,-10},{2:C},{when:d}), ein umbenannter wird also abgelehnt;{{,}}und einzelne Klammern werden ebenfalls geschützt. Keine ICU-Prüfung, keine Plurale. - Ein fehlendes Ziel wird mit den Standard-Headern angelegt.
- Abgelehnte Keys. Ein Wert, den das Ziel als typisierten, Designer- oder Markup-Eintrag hält, oder ein Key, der nicht zurückgelesen werden könnte, lässt das Schreiben mit einem
AdapterErrorscheitern, der ihn nennt. - Fehler. Ungültiges XML, ein Wurzelelement außer
<root>und eine DTD oder Entity werden abgelehnt.
Dokumentreihenfolge der Keys
Die JSON-Formate, YAML und ARB erhalten die Dokumentreihenfolge: Ganzzahlartige Keys wie "404" werden nicht nach vorn gehoben, neue Keys werden in Quellreihenfolge angehängt, und ARB-Metadaten behalten ihre Position. XLIFF aktualisiert Targets an Ort und Stelle, seine Reihenfolge ändert sich also nie.
Gepunktete Keys und Kollisionen
In i18next-json, vue-i18n-json und next-intl-json übersteht ein wörtliches gepunktetes Blatt wie "foo.bar" den Roundtrip so, wie es geschrieben ist; ngx-translate-json liest es als verschachtelten Pfad. In den anderen Formaten scheitert ein Pfad, der auf beide Arten geschrieben ist ("foo.bar" neben "foo": { "bar": ... }), mit INVALID_; ngx-translate-json lehnt flache gepunktete Keys neben verschachtelten Objekten und gepunktete Keys in verschachtelten Objekten mit MIXED_ ab.
Wie Dateien gelesen und geschrieben werden
- Grenzen. Eingabegröße und Verschachtelungstiefe sind begrenzt (
INPUT_,TOO_ LARGE MAX_).DEPTH_ EXCEEDED - Atomares Schreiben. Eine temporäre Datei wird an ihren Platz umbenannt, sodass nie eine halbe Datei bleibt.
- Layout. Die XML-Formate behalten Zeilenende und abschließenden Zeilenumbruch und rücken neue Elemente wie ihre Nachbarn ein. Ein neuer gettext-Eintrag folgt nach einer Leerzeile; eine neu angelegte
.ponennt ihre Locale inLanguage(pt_).BR - Nicht-String-Blätter. In den JSON-Formaten, YAML und ARB wird ein Blatt vom Typ Zahl, Boolean oder null akzeptiert, aber nie übersetzt, und ein Neuschrieb verwirft es; ein Array scheitert mit
INVALID_.STRUCTURE - Fehler sind strukturiert und geheimnisfrei; siehe Fehlercodes der Format-Adapter.
Formate von außerhalb verbatra
Ein weiteres Format kann aus deinem eigenen Adapter mit einer custom:-Id wie custom:toml kommen, über das SDK als vertrauenswürdiger Code ausgeführt: siehe Einen eigenen Format-Adapter schreiben.
Inline-Markup in Werten
Die Markup-Paritätsprüfung gilt in jedem Format, pro Tag:
xliffschützt seine eigenen Inline-Elemente als Platzhalter; anderes HTML wie<b>wird als Markup verglichen.next-intl-jsonundarbbehandeln ein gepaartes<b>...</b>als Platzhalter und vergleichen ein selbstschließendes<br/>als Markup; ein Tag mit Attributen ist ungültiges ICU und wird abgelehnt.android-xmlvergleicht dekodierte Werte,<b>ist also<b>.- Jedes andere Format hat kein Markup-Konzept, nur diese Prüfung sieht es also.