Die CLI übersetzt achtzehn Dateiformate. Das Format wird anhand der Dateiendung erkannt. Mit format in einem files[]-Eintrag kannst du es überschreiben – oder es für die drei Formate angeben, die es immer benötigen (yaml-openapi, yaml-root-key, android).
| Format | Dateiendungen | format-Wert | Hinweise |
|---|---|---|---|
| JSON | .json | json | Schlüssel/Wert. Unterstützt Schlüsselsteuerungen. |
| JSONC | .jsonc | jsonc | JSON mit Kommentaren. Kommentare bleiben erhalten und dienen gleichzeitig als Hinweise für Übersetzer. |
| YAML | .yaml, .yml | yaml | Generisches YAML. Jeder String-Wert wird übersetzt; Schlüssel und Struktur bleiben erhalten. |
| OpenAPI YAML | .yaml, .yml | yaml-openapi | OpenAPI-Spezifikationen. Setze format explizit — einfaches .yaml wird automatisch als yaml erkannt. |
| Sprache als YAML-Stammschlüssel | .yaml, .yml | yaml-root-key | Die Sprache ist der YAML-Stammschlüssel (Rails config/locales). Der Stammschlüssel wird auf die Zielsprache umgeschrieben. Gib format daher explizit an. |
| Markdown | .md | md | Fließtext wird übersetzt; Frontmatter nur per Opt-in. |
| MDX | .mdx | mdx | Markdown + JSX. Component Props nur per Opt-in. |
| Markdoc | .mdoc | markdoc | Markdown + Tags. Frontmatter + Tag-Attribute. |
| TypeScript | .ts, .mts, .cts | typescript | Sprache-Module (export default { … }). String-Literale werden übersetzt; Code bleibt erhalten. |
| Gettext PO | .po | po | msgstr wird übersetzt; msgid, Kommentare und Header bleiben erhalten. |
| Flutter ARB | .arb | flutter | String-Werte werden übersetzt; @-Metadaten und {placeholders} bleiben erhalten. |
| Android | .xml | android | strings.xml. Setze format explizit — .xml wird nicht automatisch erkannt. |
| Xcode strings | .strings | xcode-strings | Werte werden übersetzt; Schlüssel bleiben erhalten. |
| Xcode String Catalog | .xcstrings | xcode-xcstrings | Eine Datei enthält jede Sprache — die Zielsprachen werden zurück in dieselbe Datei geschrieben (siehe unten). |
| Xcode stringsdict | .stringsdict | xcode-stringsdict | Pluralformen werden übersetzt; Steuerungsschlüssel fürs Format bleiben erhalten. |
| XLIFF | .xlf, .xliff | xliff | <source> bleibt erhalten, <target> wird pro Einheit geschrieben. Versionen 1.2 und 2.0. |
| SubRip | .srt | srt | Untertiteltext wird übersetzt; Indizes und Timecodes bleiben unverändert. |
| PHP | .php | php | Laravel return [ … ]. String-Werte werden übersetzt; Schlüssel, Zahlen und Struktur bleiben erhalten. |
Einmal von Anfang bis Ende
Das Demo-Projekt ist eine kleine Sandbox mit Dokument- und Datenformaten — JSON, JSONC, Markdown, MDX, Markdoc und OpenAPI YAML — jeweils mit genau der Konfiguration, die dafür nötig ist. Klone es mit npx degit lingodotdev/lingo.dev/demo/new-cli my-lingo-demo und pushe es. App- und Framework-Formate sind nicht enthalten — dafür gibt es die Beispielprojekte mit einem vollständigen Repository pro Framework, und die formatspezifischen Snippets unten zeigen die Konfiguration.
npx degit lingodotdev/lingo.dev/demo/new-cli my-lingo-demo
cd my-lingo-demoJSON und JSONC#
Einfache Schlüssel/Wert-Übersetzung. Jeder String-Wert wird übersetzt, sofern keine Schlüsselsteuerung etwas anderes vorgibt.
{ "pattern": "content/en/app.json", "lockedKeys": ["meta.version"] }JSONC behält zusätzlich Kommentare bei, die die Engine als Kontext liest — siehe Hinweise für Übersetzer.
{ "pattern": "content/en/settings.jsonc", "preservedKeys": ["featureFlags"] }Markdown, MDX und Markdoc#
Der Fließtext wird standardmäßig übersetzt. Frontmatter und eingebettete Komponenten werden nicht übersetzt, außer du aktivierst sie per Opt-in.
Frontmatter#
Gib die Frontmatter-Felder, die übersetzt werden sollen, mit translateFrontmatterFields an:
{
"pattern": "content/en/guide.md",
"translateFrontmatterFields": ["title", "description"]
}MDX-Component-Props#
In MDX übersetzt du mit translateComponentProps gezielt bestimmte Props bestimmter Komponenten:
{
"pattern": "content/en/landing.mdx",
"translateFrontmatterFields": ["title"],
"translateComponentProps": [{ "component": ["Hero", "Callout"], "props": ["title", "body"] }]
}Dadurch werden die Props title und body auf <Hero> und <Callout> übersetzt; alle anderen Props bleiben unberührt.
Markdoc#
Markdoc funktioniert wie Markdown, wobei Frontmatter und Tag-Attribute erhalten bleiben:
{
"pattern": "content/en/changelog.mdoc",
"translateFrontmatterFields": ["title"]
}YAML#
Generisches YAML wird über .yaml/.yml automatisch erkannt — jeder String-Wert wird übersetzt, Schlüssel und Struktur bleiben erhalten:
{ "pattern": "content/en/strings.yaml" }OpenAPI-Spezifikationen sind ein Sonderfall: Sie nutzen dieselbe Dateiendung .yaml, brauchen aber ein explizites format, damit die Engine nur nutzerseitige Felder (Zusammenfassungen, Beschreibungen) übersetzt und Schema-Schlüssel, Pfade und Operation IDs unberührt lässt:
{ "pattern": "content/en/api.yaml", "format": "yaml-openapi" }Rails-typische Sprachdateien sind der andere Sonderfall: Die Sprache ist der YAML-Stammschlüssel (en:), und die Zieldatei muss mit der Zielsprache (es:) als Wurzeleintrag beginnen. Gib dafür ebenfalls format explizit an:
{ "pattern": "config/locales/en.yml", "format": "yaml-root-key" }App- und Framework-Formate#
PO, Flutter ARB, Xcode .strings, Xcode .stringsdict, TypeScript-Sprache-Module, XLIFF, SubRip und PHP folgen alle derselben Regel: Übersetzbarer Text wird übersetzt, alles Strukturelle bleibt erhalten (Schlüssel, IDs, Metadaten, Platzhalter, Timecodes, Code, Formatierung). Alle werden anhand ihrer Dateiendung automatisch erkannt — richte einfach ein Muster auf die Quelldatei:
{ "pattern": "lib/l10n/app_en.arb" }
{ "pattern": "locales/en.po" }
{ "pattern": "Localizable.strings" }
{ "pattern": "l10n/en.xlf" }Eines davon braucht ein explizites format, weil seine Dateiendung für die automatische Erkennung zu mehrdeutig ist:
{ "pattern": "res/values/strings.xml", "format": "android" }Xcode String Catalogs#
Eine .xcstrings-Datei (String Catalog) enthält alle Sprachen in einer einzigen Datei. Es gibt keinen Ausgabe-Pfad pro Sprache — das CLI liest die Quell-Sprache und schreibt jede Zielsprache zurück in dieselbe Datei:
{ "pattern": "Localizable.xcstrings" }Im Katalog mit "shouldTranslate": false markierte Zeichenfolgen werden übersprungen — die CLI lässt sie unübersetzt und unverändert.
Ausgabepfade#
Das Muster bezeichnet deine Quelldatei; alle Zielpfade werden daraus abgeleitet. Dabei gelten vier Regeln in dieser Reihenfolge:
- Ein kompletter Pfadabschnitt oder Dateiname, der die Sprache ist — der Regelfall.
content/en/app.json→content/de/app.json,locales/en.json→locales/de.json. - Eine Sprache am Ende eines Pfadabschnitts oder Dateinamens, für Layouts, die sie so schreiben — Android, Xcode
.strings/.stringsdict, Flutter undyaml-root-key.res/values-en/→res/values-de/,app_en.arb→app_de.arb,devise.en.yml→devise.de.yml. - Der plattformspezifisch reservierte Name für die Standardsprache, ganz ohne Sprache im Pfad. Androids schlichtes
res/values/wird zures/values-de/, und XcodesBase.lprojwird zude.lproj. - Der String Catalog, bei dem der Zielpfad identisch mit dem Quellpfad ist, weil eine Datei alle Sprachen enthält.
Android ist die einzige Plattform, deren Zielpfade nicht BCP 47 folgen: Die CLI schreibt den Ressourcenqualifizierer, den Android tatsächlich ausliest. Deshalb landet pt-BR in values-pt-rBR/ und zh-Hans in values-b+zh+Hans/.
Wenn keine der Regeln greift — die Quellsprache taucht im Pfad nirgends auf — legt die CLI ersatzweise ein Verzeichnis <locale>/ neben der Datei an, und lingo push weist dich darauf hin, dass die Zuordnung nur geschätzt wurde. Nimm diese Warnung als Hinweis, dass das Muster nicht stimmt. Siehe Konfiguration.
Du kommst vom Legacy CLI?#
Die meisten Formate des Legacy CLI gibt es inzwischen auch im aktuellen CLI (PO, XLIFF, Android/Xcode strings, Flutter ARB und mehr — siehe Tabelle oben). Ein paar weniger verbreitete Formate (z. B. CSV, HTML, MJML, .properties) werden noch nicht unterstützt; bis dein Format dazukommt, findest du die Infos in der Legacy CLI-Dokumentation.
