A Guide to Translation File Formats: JSON, YAML, XLIFF, PO, and More
If you support more than one platform, you've probably already hit the problem: your web app wants flat JSON, your iOS app wants .strings, your Android app wants XML resources, and your backend emails want gettext. None of these formats are wrong — they're just built for different ecosystems. Here's a quick reference.
JSON (flat or nested)
The default for most web and JavaScript projects. Flat JSON ({"hero.title": "Welcome"}) is simple to diff and merge; nested JSON ({"hero": {"title": "Welcome"}}) mirrors how many i18n libraries expect keys to be organized. Both are just objects, so almost any tool can read and write them without special parsing.
YAML
Popular in Ruby on Rails and some JavaScript frameworks. Functionally similar to nested JSON but more human-readable, since it drops braces and quotes in favor of indentation. The trade-off is that YAML is whitespace-sensitive, so a misplaced indent can silently break a key's nesting.
Android XML resources
Android's native string format (strings.xml), with its own escaping rules for apostrophes and quotes, and built-in support for plural forms via <plurals> blocks. If you're shipping a native Android app, this is the format your build actually consumes — everything else needs to be converted into it eventually.
iOS .strings and .stringsdict
Apple's equivalent: simple key-value pairs for most text, with a separate .stringsdict format for pluralization rules that vary by language. Straightforward to read, but iOS's plural handling is different enough from Android's that a direct one-to-one conversion between the two isn't always possible without some manual adjustment.
.properties (Java)
A plain key-value format going back to early Java, still common in backend services and some Android tooling. No nesting, no data types — just key=value lines — which makes it easy to parse but limited for anything beyond flat strings.
.arb (Flutter)
Application Resource Bundle, used by Flutter's intl package. Looks like JSON with extra @-prefixed metadata keys describing each string (description, placeholders, plural rules) — the metadata is what makes it more than plain JSON, and most tools need to specifically filter it out to get at the actual translatable text.
.po / gettext
The standard for a huge range of open-source and Linux-ecosystem software, plus many Python and PHP backends. Uses msgid (source text) and msgstr (translation) pairs, often with a msgctxt field to disambiguate identical source strings used in different contexts — which maps naturally onto a translation key.
XLIFF
An XML-based standard designed specifically for exchanging translation work between tools and professional translation agencies. More verbose than the alternatives, but it's built to carry translation status, notes, and metadata in a way that's understood across the localization industry, not just one specific framework.
The practical takeaway
You don't need to pick one format and force every platform to use it — you need a translation source of truth that can export into whichever format each of your platforms actually consumes, on demand, without you hand-converting files every release. That's the difference between "we support five platforms" being a one-click export and being a recurring manual chore.