Here's a pattern we see again and again: a team finishes a product in English, decides to "add a few languages", and discovers that the hard part was never the translation — it was getting the strings out of the code cleanly, fitting longer text into fixed buttons, and explaining to a translator what btn_submit_2 actually means.
Almost all of that is preventable. Run this checklist before the first handoff and you'll save yourself a round of bug-fixing, re-exports and awkward "why is the German cut off?" screenshots.
1. Externalize every string
No user-facing text should live inside your logic. Move it into resource files — .json, .xml, .strings, .po, .resx or .arb, whatever your framework uses — with a stable key for each entry. If a translator has to open a .js file to find text, the setup isn't ready.
Watch for the sneaky ones: error messages, email templates, push notifications, validation text, chart labels, PDF exports, and anything concatenated together at runtime.
2. Never build sentences by concatenation
This looks harmless:
"You have " + count + " new messages"
...but word order, pluralization and grammar differ by language, and a translator can't reorder a sentence they only see in fragments. Use a single string with a placeholder — "You have {count} new messages" — and a proper plural mechanism (ICU MessageFormat, plurals in Android, .stringsdict on iOS). Arabic has six plural forms; English has two.
3. Give translators context
A key like title with the value "Post" is ambiguous: is it a noun (a blog post) or a verb (to post)? They translate to completely different words. Add a comment or description field to each string, and where you can, attach a screenshot or screen name. Context is the single biggest quality lever you control for free.
4. Plan for text expansion
Translated text is rarely the same length as the source. A rough rule: text from English grows 15–35% in most European languages, and a short UI label can double. CJK languages are often shorter but taller. Design flexible containers, avoid fixed-width buttons, and never hard-code line breaks inside a sentence.
The fastest way to catch overflow early is pseudo-localization: replace your strings with accented, padded versions ([!!! Ëdìt pròfílé !!!]) and run the app. Anything that clips, truncates or breaks layout shows up before a translator is even involved.
5. Externalize formats, not just words
Dates, numbers, currencies, units and address formats are localization too. 03/04/2026 is March 4th in the US and April 3rd almost everywhere else. Use locale-aware formatting (your platform's Intl / ICU libraries) instead of building these strings by hand.
6. Check your bidirectional (RTL) readiness
If Arabic, Hebrew, Persian or Urdu are on your roadmap — even "maybe later" — verify the UI mirrors correctly now. Use logical properties (start/end instead of left/right), and test that icons, progress bars and back-buttons flip the right way.
7. Decide your file and delivery flow
Will you export to a translation management system, share files over a repo, or use a connector? Agree on the format, the encoding (UTF-8, always), and how updated strings get re-sent. A clean, repeatable export beats a heroic one-off every time.
The short version
- Every string externalized, with stable keys
- Placeholders and proper plurals — no concatenation
- A comment or screenshot for each ambiguous string
- Flexible layouts + a pseudo-localization pass
- Locale-aware dates, numbers and currencies
- RTL-safe styling if it's anywhere on the roadmap
- UTF-8 files and an agreed update flow
Do these seven things and your first localization round will feel less like firefighting and more like a clean build. The translators get clarity, your layout survives, and you ship in five languages on roughly the schedule you ship in one.