When ChatGPT or DeepL is good enough
If you have five UI strings, no placeholders, no plurals, and one target language, paste away. A quick GPT pass on your iOS strings or a DeepL pass on your Android strings will usually give you something shippable, and you'll eyeball the result in seconds.
The reason to keep reading is that mobile string files are not plain text. They carry format specifiers, plural categories, and structural syntax that a chat prompt happily rewrites — and you won't see the damage until QA, or a crash report. Here's what actually breaks.
Failure mode 1: corrupted placeholders (%@, %1$s)
This is the most common answer to "why is my app translation wrong." iOS uses %@, %lld, and positional %1$@; Android uses %s, %d, and %1$s. LLMs and DeepL routinely translate, reorder, or "tidy" these tokens — turning %@ into a translated word, dropping the $ in a positional arg, or swapping the order without renumbering.
// BEFORE (source, en)
"welcome_user" = "Welcome back, %@! You have %lld new messages.";
// AFTER — pasted through a chatbot, German
"welcome_user" = "Willkommen zurück, %@! Sie haben %lld neue Nachrichten."; // ok this time
"items_left" = "%1$s von %2$s" -> "%2$s von %1$s" // reordered, NOT renumbered -> wrong values or crash
On iOS a mismatched specifier type is an outright format crash; on Android a lost positional index silently prints the wrong variable.
Fix: strings.dev applies placeholder protection — %@, %lld, %1$s and friends are locked as non-translatable tokens and validated on the way out, so they survive the round trip intact. URLs, emails, @handles, and proper nouns are preserved the same way.
Failure mode 2: flattened plural categories
An iOS String Catalog (.xcstrings) plural variation and an Android <plurals> block are not one string — they're a set of quantity categories. Chat-based .xcstrings translation tends to collapse them, and this is where DIY app translation with an LLM quietly falls apart: many languages need categories English doesn't have. Russian and Polish use one/few/many/other; Arabic uses zero/one/two/few/many/other.
<!-- BEFORE: Android source -->
<plurals name="photos">
<item quantity="one">%d photo</item>
<item quantity="other">%d photos</item>
</plurals>
<!-- AFTER: chatbot gives you Russian with only the two English categories -->
<plurals name="photos">
<item quantity="one">%d фото</item>
<item quantity="other">%d фото</item> <!-- missing "few" and "many" -> wrong grammar for 2,3,4,21… -->
</plurals>
Fix: strings.dev understands .xcstrings plural variations and Android <plurals> natively and emits the full set of quantity categories each target locale requires — same format in, same format out.
Failure mode 3: brand-term drift across files
Paste ten batches into a chat window and your product name, feature names, and UI terminology come back translated inconsistently — "Boards" localized in screen A, kept in English in screen B, and rendered a third way in the onboarding file. There's no memory tying the batches together.
Fix: brand-phrase placeholder protection keeps terms you designate (product name, feature names) identical across every string and every file. Deeper brand context is part of Indie Plus ($20/mo, or $10/mo billed annually).
Failure mode 4: lost context
"Post" is a verb on a button and a noun in a list. A translator — human or model — needs to know which. A bare string in a chat prompt gives the model nothing, so it guesses, and half the time it guesses wrong.
Fix: strings.dev feeds your app-description context into every translation so the model knows what your app does, and you can attach per-string translation notes ("this is a verb on a compose button") to disambiguate the tricky ones.
Failure mode 5: the tedium (and drift) across 52 locale files
Even if every paste were perfect, doing it by hand across dozens of locales is the real cost. Export, paste, prompt, copy back, reassemble the file, repeat — per language, every release. Miss one string and that locale silently falls back to English. This is the part no amount of prompt-crafting fixes.
Fix: you upload the native file — Xcode .xcloc for Apple platforms or strings.xml for Android — pick your locales, and get the same native format back in minutes. No XLIFF conversion, no manual reassembly. A QA & analytics dashboard flags any failed translations and lets you retry them (Indie Plus, $20/mo or $10/mo billed annually). You can wire the whole loop into CI or a git hook with the per-project CLI, REST API, or MCP server so continuous localization runs on every merge.
Side by side
|
ChatGPT / DeepL paste |
strings.dev |
%@ / %1$s placeholders |
Frequently altered or reordered |
Locked and validated |
.xcstrings / <plurals> categories |
Often flattened to English set |
Full per-locale category set |
| Brand terms across files |
Drift between batches |
Held constant everywhere |
| Per-string context |
None unless you add it every time |
App-description context + per-string notes |
| Native file round-trip |
Manual export/reassemble |
.xcloc / strings.xml in, same out |
| Failed-translation QA |
You find it in prod |
Dashboard flags + retry (Indie Plus) |
Placeholder protection, plural handling, and the native round-trip work on the free Indie tier (1 project, 1 language, unlimited words). Unlimited languages, brand context, a second project (2 projects), and the QA & analytics dashboard are Indie Plus — $20/mo, or $10/mo billed annually.
Honest scope
strings.dev localizes your in-app native strings — not your website copy, and not your App Store or Play Store listing metadata or screenshots (translate those separately). What it does, it does end to end: native format in, native format out.
You can start free. The Indie tier is free forever — 1 project, 1 language, unlimited word translations, with app and brand localization — which is enough to test the full round trip on a real file. Unlimited languages, a second project (2 projects total), brand context, and the QA & analytics dashboard are Indie Plus at $20/mo, or $10/mo billed annually. See pricing for the full breakdown, or try the free app localization tier.