Zum Inhalt springen
Zum Inhalt springen

Referenz / Konfiguration

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.

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:

formatDateienPlatzhalterPluraleFehlende ZieldateiNative Platzhaltersyntax
i18next-jsoni18next-JSON (.json){{name}}, $t(...)CLDR-Suffix am Keyangelegt{{name}}
vue-i18n-jsonvue-i18n-JSON (.json){name}, {0}Pipe im Wertangelegt{name}, %{name}, ${name}
next-intl-jsonnext-intl-JSON (.json)ICU-Argumente und -TagsICU plural, selectordinalangelegt{name}, %{name}, ${name}
ngx-translate-jsonngx-translate-JSON (.json){{name}}keineangelegt{{name}}
xliffXLIFF 1.2 und 2.0 (.xlf, .xliff)Inline-Elemente, {...}keineabgelehnt{{name}}, {name}, %{name}, ${name}
yamlYAML (.yml, .yaml){{name}}keineangelegt{{name}}
arbFlutter-ARB (.arb)ICU-Argumente und -TagsICU plural, selectordinalangelegt{name}, %{name}, ${name}
propertiesJava/Spring-Properties (.properties)MessageFormat {0}, {count}keineangelegt{name}, %{name}, ${name}
apple-stringsApple-.strings, mit der zugehörigen .stringsdictprintf %@, %d.stringsdict-Kategorienangelegtprintf %s
apple-xcstringsXcode String Catalogs (.xcstrings)printf %@, %lldvariations.pluralabgelehntprintf %s
android-xmlAndroid strings.xmlprintf %s, %1$s<plurals>-Quantitätenangelegtprintf %s
gettext-pogettext (.po, .pot)printf, %(name)smsgstr[n]angelegtprintf %s, %(name)s
iniINI (.ini){name}, {0}keineangelegt{name}, %{name}, ${name}
resx.NET-Ressourcen (.resx)Composite {0}, {1:C}, benannt {name}keineangelegt{{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 (_zero, _one, _two, _few, _many, _other). 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_STRUCTURE.

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_UNREADABLE. Ein einzelner Namespace funktioniert wie konfiguriert:

verbatra.config.ts
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.ts

Nur 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 id der Unit, dann resname, dann eine Position, die sich verschiebt, wenn Units wandern; gib also jeder Unit eine id. Eine 2.0-Unit mit mehreren Segmenten bekommt Keys der Form <id>#<n>. Ein doppelter Key scheitert mit INVALID_STRUCTURE.
  • Quelle oder Übersetzung. Ein Dokument ist die Quelle, wenn die Locale zu seiner source-language passt (srcLang in 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 (en zu en-GB) muss target-language (trgLang) deklarieren.
  • Fehlende Werte. Ein <target>, das fehlt, leer ist oder in 1.2 mit state="new" oder "needs-translation" markiert ist, gilt als fehlend, ebenso ein 2.0-Target, das seiner Quelle gleicht, in einem Segment mit state="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-State new oder needs-translation oder ein 2.0-State initial (samt subState) wird zu translated. <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 mit INVALID_STRUCTURE scheitern und nennt den Key; eine unlesbare Quelle lässt es ohne Key scheitern. verbatra extract hängt Quell-Units nur mit <source> an; in 2.0 muss der Key ein gültiges NMTOKEN sein (u1#0 wird abgelehnt).
  • Inline-Markup. Die 1.2-Elemente g, x, bx, ex, bpt, ept, ph, it, mrk, die 2.0-Elemente ph, pc, sc, ec, mrk, sm, em, cp und jede {...}-Folge sind in beiden Versionen geschützte Platzhalter. Beim Schreiben bleiben nur diese (plus das 1.2-<sub> innerhalb von bpt, ept, ph, it) Markup; alles andere, etwa <b>, wird zu Text.
  • Escaping. Text wird als Text gelesen (A &amp; B ist A & B) und beim Schreiben einmal escaped; Text, der genau einem erlaubten Element entspricht, etwa &lt;x id="1"/&gt;, wird als dieses Element geschrieben, <!DOCTYPE und <!ENTITY als 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_STRUCTURE, fehlerhafte Syntax scheitert mit INVALID_YAML, 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-json behandelt.
  • Metadaten werden nie übersetzt und an ihrer Position wieder eingefügt; ein beschädigtes vorhandenes Ziel lässt das Schreiben scheitern. @key.description ist 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.
  • @@locale steht vorne. Ein neu angelegtes Ziel beginnt damit, in der Schreibweise von gen-l10n (pt_BR); 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 scheitert 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 \uXXXX geschrieben.
  • 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 Typ plural, select, selectordinal und choice. 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_STRUCTURE; speichere sie neu als UTF-8.
  • Kommentare. Ein /* ... */-Kommentar vor einem Eintrag ist nur lesbarer Kontext; //-Kommentare bleiben erhalten. Die Escapes \", \\, \n, \t und \U werden 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 .stringsdict eingeschlossen.
  • 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_count_one), und nur die Kategorien, die eine Locale hat, überstehen den Roundtrip. Fehler nennen Datei und Key; Format-Key, Variablenname und Werttyp überstehen einen Neuschrieb.
  • Layout. {locale}.lproj/Localizable.strings braucht 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.pattern braucht weiterhin {locale}, aber {locale} wird zu einem leeren String, sodass sich jede Locale zur selben Datei auflöst ({locale}Localizable.xcstrings ergibt Localizable.xcstrings). Jeder Schreiber wird darauf serialisiert, Locales laufen also auch mit --concurrency nacheinander.
  • Keys. Ein Key ohne sourceLanguage-Localization verwendet den Key-Text als Quelle; eine fehlende Ziel-Localization zählt als nicht übersetzt.
  • Plurale unter variations.plural werden zu <key>_<category>, nur für die vorhandenen Kategorien.
  • Platzhalter sind printf, wie bei .strings; %lld ist 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> zu key[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, \t und 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. --prune weiß 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.

  • msgctxt wird mit U+E000 an seine msgid zu 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-Forms bleibt wörtlich erhalten, und nur sein nplurals begrenzt die Indizes; Plural-Einträge ohne ihn werden abgelehnt, wie es msgfmt --check tut.
  • 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 .pot mit leerem msgstr wird sauber gelesen, aber in einem Quellkatalog ist jeder msgstr der zu übersetzende Text, ein leerer wird also mit SOURCE_VALUE_EMPTY übersprungen.
  • 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)s eingeschlossen.
  • Fehler nennen die msgid und die Zeile. --prune weiß 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] ist home.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, \t dekodiert 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 AdapterError aus; 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, bekommt xml:space="preserve".
  • Nicht übersetzt. <data> mit type oder mimetype und 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 AdapterError scheitern, 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_STRUCTURE; ngx-translate-json lehnt flache gepunktete Keys neben verschachtelten Objekten und gepunktete Keys in verschachtelten Objekten mit MIXED_STRUCTURE 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 .po nennt ihre Locale in Language (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:

  • xliff schützt seine eigenen Inline-Elemente als Platzhalter; anderes HTML wie <b> wird als Markup verglichen.
  • next-intl-json und arb behandeln 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-xml vergleicht dekodierte Werte, &lt;b&gt; ist also <b>.
  • Jedes andere Format hat kein Markup-Konzept, nur diese Prüfung sieht es also.
Auf GitHub bearbeiten

Auf dieser Seite