Format notes
All readers produce the same model (catalog.Entry): key, value or per-category plural forms, optional source text, comment, fuzzy flag and a bag of format-specific data that writers use to restore the file. Writers regenerate the file from the model, so formatting is normalized and comments the model does not carry are lost.
JSON (i18next)
- Flat (
{"a.b": "x"}) and nested ({"a": {"b": "x"}}) are detected from the file and written back the same way; indentation (2, 4, tab) is preserved. If nesting would be ambiguous on write (a key that is both leaf and branch) the file is written flat. - Plural suffixes
_zero _one _two _few _many _otherare folded into one entry named by the stem:items_one+items_otherbecomeitemswith formsoneandother. A stem that also exists as a plain key is not folded. - Arrays are flattened as
key.0,key.1and rebuilt as arrays on write in nested files. - Line numbers come from locating each key in the source text, in document order.
YAML (Rails)
en: root key gives the locale. A mapping whose keys are only plural categories (including one or other) is a plural entry. Values are read from the YAML node tree, so yes/no and numbers stay the strings the file shows.
gettext PO/POT
Own parser: msgctxt (stored as ctx\x04msgid, the gettext convention), msgid_plural, msgstr[n], multi-line strings, # / #. / #: / #, / #| comments, obsolete #~ entries ignored, header block kept. Locale comes from Language: and falls back to the path. Because every target carries its msgids, the base catalog is synthesized from them: value = msgid, plural forms = msgid and msgid_plural as one/other.
Android
<string>, <plurals><item quantity>, <string-array><item> (array items become keys name[i]), translatable="false" entries are excluded from all checks. Values are raw XML fragments (inline <b>, <xliff:g> and entities stay as written) with Android escapes decoded: \', \", \n, \@, \?, \uXXXX. Written back with escapes restored.
iOS
.strings: quoted key/value pairs with /* comment */ attached to the next entry, \", \n, \UXXXX escapes, UTF-8 or UTF-16 (BOM detected). .stringsdict: plist; the NSStringLocalizedFormatKey and variable name are kept so files round-trip.
XLIFF
1.2 (trans-unit, source, target, note, approved, state) and 2.0 (unit, segment, notes). target-language / trgLang gives the locale; source text becomes the base. Fuzzy means needs-review-translation-style states, approved="no", or 2.0 state="initial" with a non-empty target.
.properties
Continuation lines, = : or whitespace separators, # / ! comments, \uXXXX including surrogate pairs. Written with all non-ASCII as \uXXXX. messages.properties is the base for messages_de.properties.
ARB
JSON with @@locale, @key metadata (description, placeholders) preserved and written back next to its key. Messages are ICU, so ARB catalogs always get ICU syntax validation.