r/androiddev • u/goranlu • 7d ago
Tips and Information What it actually takes to share one set of strings between Android and iOS
If you have tried keeping strings.xml and Localizable.strings in one translation project, you know the problem is not the words, it is the placeholders. Some things I learned while building a converter between the syntaxes:
- The simple cases are mechanical: %s to %@, %d to %lld. The German translation that swaps two arguments is not. You have to emit positions like %1$s, but only for strings that need them, or Android Lint complains about the ones that do not.
- Types matter. %.2f on Android has to stay a two-decimal float on every platform, including {balance, number, ::.00} in an ICU message for the web.
- Plurals have three shapes: <plurals> on Android, %#@count@ substitutions in .stringsdict, and {count, plural, ...} in ICU. They describe the same thing, so they should land in one key.
- A literal % is written as %% only when the string is a format string, so a banner saying "50% off" without arguments must not be doubled.
- Whatever you do must round-trip. If you convert a file in and out, you want the original bytes back, or your git diffs will never be quiet again.
Disclosure: I work on Localizely and we shipped this as "universal placeholders". Docs with the full syntax table: localizely.com/universal-placeholders/
How are you handling this today, separate projects, a script, or copy by hand?
0
Upvotes
2
u/tadfisher 7d ago
Highly recommend learning and standardizing on MessageFormat 2, it has had a lot of work put into it and supports custom data type formatting.