---
title: "Formate"
description: "Alle i18n-Dateiformate, die verbatra unterstützt, wie jedes seine Dateien liest und schreibt und was ein Schreibvorgang erhält, damit Diffs sauber bleiben."
type: "reference"
---
# 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](https://verbatra.kreitz-webdev.de/de/docs/config-file.md) auf eine dieser Ids:

| `format` | Dateien | Platzhalter | Plurale | Fehlende Zieldatei | [Native Platzhaltersyntax](https://verbatra.kreitz-webdev.de/de/docs/error-codes.md#foreign_placeholder_changed) <AvailableFrom version="0.12.0" /> |
| --- | --- | --- | --- | --- | --- |
| `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](https://verbatra.kreitz-webdev.de/de/docs/translation-safety.md) vergleicht.

## Die vier JSON-Formate [#die-vier-json-formate]

Alle vier lesen verschachtelte JSON-Objekte mit String-Blättern.

### i18next-json [#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 [#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 [#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](https://verbatra.kreitz-webdev.de/de/docs/translation-safety.md#plural-zweige-je-zielsprache). Ein Wert, der nicht als ICU parst, wird als ungültig gemeldet und übersprungen.

### ngx-translate-json [#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 [#die-erfindungs-schranke-für-einzelklammern]

<AvailableFrom version="0.9.0" />

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 [#namespace-layouts]

[`files.pattern`](https://verbatra.kreitz-webdev.de/de/docs/config-file.md#locales-und-dateien) 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:

```ts title="verbatra.config.ts"
files: {
  pattern: "public/locales/{locale}/common.json",
},
```

### Eine Konfiguration pro Namespace [#eine-konfiguration-pro-namespace]

Schreib für mehrere Namespaces je eine Konfiguration und führe sie nacheinander aus:

```bash
verbatra translate --config verbatra.common.config.ts
verbatra translate --config verbatra.auth.config.ts
```

<Callout type="warn" title="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.
</Callout>

## XLIFF [#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](https://verbatra.kreitz-webdev.de/de/docs/manual-translation.md).
- **Abgelehnte Eingabe.** Ein Dokument mit einer DTD- oder Entity-Deklaration scheitert mit `INVALID_XML`.

## YAML [#yaml]

Ein verschachtelter Baum wie bei den JSON-Formaten, mit i18nexts `{{double-brace}}`-Interpolation und der [Erfindungs-Schranke](#die-erfindungs-schranke-für-einzelklammern), 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 [#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 [#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 [#apple-strings]

<AvailableFrom version="0.10.0" />

`"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) [#xcode-string-catalogs-xcstrings]

<AvailableFrom version="0.10.0" />

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 [#android-stringsxml]

<AvailableFrom version="0.10.0" />

`res/values/strings.xml` für die Quelle und `res/values-<qualifier>/strings.xml` pro Ziel; setze `files.localeStyle: "android"` ([Konfiguration](https://verbatra.kreitz-webdev.de/de/docs/config-file.md#locales-und-dateien)).

- **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 [#gettext-popot]

<AvailableFrom version="0.10.0" />

`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`](https://verbatra.kreitz-webdev.de/de/docs/error-codes.md#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 [#ini]

<AvailableFrom version="0.11.0" />

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 [#net-resx]

<AvailableFrom version="0.11.0" />

`<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 [#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 [#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 [#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](https://verbatra.kreitz-webdev.de/de/docs/error-codes.md#adapter-error-codes).

## Formate von außerhalb verbatra [#formate-von-außerhalb-verbatra]

<AvailableFrom version="0.11.0" />

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](https://verbatra.kreitz-webdev.de/de/docs/custom-format-adapters.md).

## Inline-Markup in Werten [#inline-markup-in-werten]

<AvailableFrom version="0.11.0" />

Die [Markup-Paritätsprüfung](https://verbatra.kreitz-webdev.de/de/docs/translation-safety.md#inline-markup-parität) 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.
