Formats

Supported translation file formats

locamorph reads and writes seven translation file formats: JSON, YAML, Android strings.xml, iOS .strings, Flutter ARB, Java properties and XLIFF. Import any of them, translate, and export files your toolchain accepts without a cleanup pass.

Every implemented format ships with a round trip test: what locamorph exports parses back identically, and translator notes travel in both directions.

At a glance

Seven formats, one pipeline

Files enter through uploads, repo syncs, S3 or the CLI, and leave the same ways. The format decides what can be expressed; locamorph maps everything onto one model of keys, values, plurals and notes.

Format Extensions Used by Plurals Import Export
JSON .json Web apps, i18next, react-intl ICU messages Yes Yes
YAML .yml .yaml Ruby on Rails ICU messages Yes Yes
Android XML .xml Native Android Native <plurals> Yes Yes
iOS Strings .strings iOS, macOS None in format Yes No
ARB .arb Flutter Native ICU Yes Yes
Java Properties .properties Java, Spring ICU in values Yes Yes
XLIFF .xlf .xliff CAT tools, Angular Native Yes Yes

Guarantees

What holds across every format

round trip

Exports parse back identically

Each format's exporter is tested against its own parser. A file that leaves locamorph and comes back carries the same keys, values, plurals and notes.

plurals

Plural forms are never dropped

Plurals normalize to CLDR categories internally. Android plurals blocks, ARB ICU messages and XLIFF groups convert without losing a form.

detection

Content based detection

Imports identify the format from the content itself with confidence scoring, so a YAML file named .txt or an ARB served as JSON still lands right.

Exports are also deterministic. Indentation, key order, nesting and plural style follow the project’s settings rather than whoever exported last, so the same keys always serialize to the same bytes and a translation diff stays down to the strings that changed.

Plurals

One plural, every format

Plurals are where converters usually cheat: they copy the text and drop the forms. locamorph maps every format’s plural syntax onto CLDR categories, so the same plural moves between all of these without losing a form. Each encoding also has its own guide, history and trade offs included.

res/values-fr/strings.xml
<plurals name="cart_items">
    <item quantity="one">%d article</item>
    <item quantity="other">%d articles</item>
</plurals>
lib/l10n/app_fr.arb
"cartItems": "{count, plural, one {{count} article} other {{count} articles}}",
"@cartItems": {
  "placeholders": { "count": {} }
}
locale/fr.json
"cart": {
  "items": "{count, plural, one {# article} other {# articles}}"
}
config/locales/fr.yml
fr:
  cart:
    items: "{count, plural, one {# article} other {# articles}}"
messages_fr.properties
cart.items={count, plural, one {# article} other {# articles}}
messages.fr.xlf
<group restype="x-gettext-plurals" resname="cart.items">
  <trans-unit id="cart.items[one]" resname="cart.items">
    <source>%d item</source>
    <target state="translated">%d article</target>
  </trans-unit>
  <trans-unit id="cart.items[other]" resname="cart.items">
    <source>%d items</source>
    <target state="translated">%d articles</target>
  </trans-unit>
</group>

One plural, six spellings, the same CLDR forms underneath. iOS .strings is missing on purpose: the format has no plural syntax.

Bring the files you already have

Drop a file on a free project and locamorph identifies the format, reads the plurals and keeps the notes. When you export, your toolchain gets exactly the shape it expects.