.strings vs .xcstrings vs strings.xml vs .arb: Localization File Formats Explained
Every mobile ecosystem invented its own localization file format, and each encodes the same three things differently: key–value strings, placeholders, and plurals. Here's a field guide to the five formats that matter — .strings, .xcstrings, strings.xml, .arb, and i18n JSON — plus how to convert between them without losing plurals or placeholders.
The five formats at a glance
| Format | Platform | Placeholders | Plurals |
|---|---|---|---|
.strings | iOS / macOS (legacy) | %@ %lld %1$@ | Separate .stringsdict |
.xcstrings | iOS / macOS (modern) | %@ %lld | Built-in variants |
strings.xml | Android | %1$s %2$d | <plurals> blocks |
.arb | Flutter | {name} ICU | ICU {n, plural, …} |
| i18n JSON | React Native / web | {{var}} | Key suffixes (_one, _other) |
What each format gets right (and wrong)
.strings — simple, but plurals live elsewhere
Flat key–value pairs, C-style escapes. Easy to parse, but plural logic requires a parallel .stringsdict, and multi-language apps mean parallel files per locale. Full walkthrough: translating .strings files.
.xcstrings — one JSON file, all languages
Apple's current format merges every language and plural variant into a single catalog Xcode maintains automatically. Best-in-class for iOS; almost nothing outside Xcode parses it correctly. Details: translating String Catalogs.
strings.xml — explicit and verbose
XML with positional format args and per-language values-xx folders. Entities (&) and embedded HTML are the classic translation casualties. Details: translating strings.xml.
.arb — ICU MessageFormat in JSON
The most expressive plural/select syntax of the group, and the most fragile: one ICU typo fails Flutter codegen. Details: translating .arb files.
i18n JSON — a convention, not a standard
Nested keys, double-brace interpolation, plural key suffixes that vary by library configuration. Structure preservation is everything. Details: React Native localization.
Converting between formats
Cross-format conversion is where hand-rolled scripts die, because the plural models don't map 1:1 — an ICU plural block must become a .stringsdict-style variant set or an i18next suffix family, per language. Localize Your App treats formats as interchangeable views over the same strings: upload any supported format, translate into any of 39 languages, and export to any other supported format. The practical wins:
- Migrate legacy
.stringsto a modern.xcstringscatalog in one pass. - Ship an iOS and Android app from one uploaded string set — same translations, same glossary, both native formats out.
- Placeholders are converted structurally (
%1$s↔ ICU ↔%@), not string-replaced, and every output is validated before download.
Whatever format you're in today, it stops being a lock-in decision — which changes the cost math for shipping more platforms.
Ship your app in 39 languages by tonight
Upload your localization file, review side by side, download ready-to-import files for every language. One-time credits from $9 — no subscription.
No subscription. Credits never expire.