Sarah's commit message was optimistic: "Add Spanish translations via ChatGPT." Three hours later, her Android app was crashing in production for Spanish users. The culprit? ChatGPT had turned "Welcome %1$s!" into "¡Bienvenido %1s!" — dropping a single character that made String.format() throw exceptions. This is exactly what happens when you feed mobile resource files to raw LLMs without format-specific safeguards.
The ChatGPT Localization Disaster Pattern
Every few months, someone in our engineering Slack shares a screenshot of their app crashing after using ChatGPT for translations. The pattern is always the same: developer copies their strings.xml or Localizable.strings file, asks ChatGPT to translate it, pastes the result back, and ships it. Then production breaks in creative ways.
This isn't developer incompetence — it's LLMs doing what they're trained to do. ChatGPT and Claude see your carefully structured resource files as natural language text that happens to have some weird formatting. They optimize for linguistic accuracy while completely ignoring the technical constraints that keep your app functional.
Here are the five ways this breaks, in order of how quickly they'll destroy your app.
1. Placeholder Corruption: The Silent App Killer
Placeholders are where raw LLMs fail first and fail hardest. Android uses positional format specifiers like %1$s and %2$d, while iOS uses %@ and numbered variants like %1$@. ChatGPT treats these as part of the text to be "improved."
Here's what ChatGPT does to a simple Android string:
<!-- Original -->
<string name="welcome_message">Welcome %1$s! You have %2$d new messages.</string>
<!-- ChatGPT Spanish translation -->
<string name="welcome_message">¡Bienvenido %1s! Tienes %2d mensajes nuevos.</string>
Notice the missing $ characters? That's enough to crash your app. String.format() expects %1$s but gets %1s, which isn't valid Android formatting. Your app throws a runtime exception every time it tries to display that string.
iOS placeholders get mangled differently:
// Original
"notifications_count" = "You have %1$@ notifications from %2$@";
// ChatGPT output
"notifications_count" = "Tienes %1$@ notificaciones de %2$@";
Sometimes ChatGPT gets it right by accident. Other times it decides %@ should become %s because it's "correcting" the format to match other languages it's seen. The inconsistency makes this particularly dangerous — your QA might not catch every permutation.
We've covered why placeholders break during translation in depth, but the core issue is that LLMs don't understand these are functional code elements, not text to be localized.
This is where things get really interesting. Android's quantityString system uses specific XML attributes that ChatGPT treats as suggestions rather than requirements.
Consider this Android plural resource:
<plurals name="item_count">
<item quantity="zero">No items</item>
<item quantity="one">%1$d item</item>
<item quantity="other">%1$d items</item>
</plurals>
ChatGPT's Spanish translation might look like:
<plurals name="item_count">
<item quantity="zero">Sin artículos</item>
<item quantity="one">%1d artículo</item>
<item quantity="other">%1d artículos</item>
</plurals>
Two problems here: the placeholder corruption we discussed above, plus ChatGPT doesn't understand that Spanish plural rules require different quantity values than English. Spanish doesn't use quantity="zero" the same way English does, and ChatGPT certainly doesn't know the CLDR plural rules that Android follows.
iOS .stringsdict files are even more fragile:
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@item_count@</string>
<key>item_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>zero</key>
<string>No items</string>
<key>one</key>
<string>%d item</string>
<key>other</key>
<string>%d items</string>
</dict>
</dict>
ChatGPT sees this nested XML structure and often breaks the hierarchy, changes key names, or drops essential metadata. The result isn't just wrong plurals — it's an unparseable file that crashes your app at startup.
For platform-specific plural handling details, check out our guides for Android plurals and iOS pluralization.
3. Structural XML and Plist Destruction
LLMs excel at understanding content but struggle with preserving rigid structural formats. Mobile resource files aren't just text — they're parsed data structures that must follow exact specifications.
ChatGPT regularly produces broken XML like this:
<!-- What ChatGPT outputs -->
<string name="app_name">Mi Aplicación</string>
<string name="description">Una aplicación increíble</string>
<!-- Missing closing tag, wrong attribute syntax, etc. -->
<!-- Or worse, completely mangled structure -->
<string name="title">Título Principal
<string name="subtitle">Subtítulo importante</string>
iOS .strings files get similar treatment:
// ChatGPT often forgets quotes or semicolons
"title" = Título Principal;
"subtitle" = "Subtítulo importante"
"description" = "Una descripción completa";
The missing quote and semicolon make the file unparseable. Your app either crashes during resource loading or silently falls back to English for all strings, depending on how your parsing handles malformed files.
CDATA sections are another common casualty:
<!-- Original with HTML content -->
<string name="terms"><![CDATA[Accept our <b>Terms of Service</b>]]></string>
<!-- ChatGPT output -->
<string name="terms">Acepta nuestros <b>Términos de Servicio</b></string>
ChatGPT stripped the CDATA wrapper, which means the <b> tags are now parsed as XML elements instead of literal text. Your app might crash trying to parse <b> as a string resource.
This one's subtle but devastating. ChatGPT doesn't distinguish between Android's %s format specifiers and iOS's %@ placeholders. It often "corrects" one platform's format to match the other, especially when translating cross-platform projects.
Here's what happens when you feed ChatGPT a mixed codebase:
// iOS original
"user_greeting" = "Hello %@, you have %1$@ messages";
// ChatGPT decides to "standardize" to Android format
"user_greeting" = "Hola %s, tienes %1$s mensajes";
Now your iOS app crashes because NSString's formatting doesn't understand %s specifiers. The reverse happens too — Android strings.xml getting iOS-style %@ placeholders that make String.format() throw exceptions.
Cross-platform teams hit this constantly because ChatGPT sees similar-looking format specifiers and assumes they're interchangeable. They're not. Platform-specific localization differences run much deeper than most developers realize.
5. Context-Free Technical String Translation
The most insidious problem: ChatGPT translates strings that should never be translated. Technical identifiers, accessibility labels, debug keys, and API constants all look like "text to be localized" to an LLM.
<!-- Before ChatGPT -->
<string name="api_endpoint_key">user_profile_data</string>
<string name="accessibility_button_id">nav_menu_button</string>
<string name="debug_tag">MainActivity_onCreate</string>
<string name="analytics_event">screen_view_dashboard</string>
<!-- After ChatGPT Spanish translation -->
<string name="api_endpoint_key">datos_perfil_usuario</string>
<string name="accessibility_button_id">botón_menú_navegación</string>
<string name="debug_tag">Actividad_Principal_onCreate</string>
<string name="analytics_event">vista_pantalla_tablero</string>
Your app now sends analytics events named "vista_pantalla_tablero" instead of "screen_view_dashboard", breaking your entire tracking system. API calls fail because the backend expects "user_profile_data" but your app sends "datos_perfil_usuario". Accessibility services can't find UI elements because their IDs changed from English to Spanish.
ChatGPT has no concept of which strings are user-facing text versus technical identifiers. It translates everything with equal enthusiasm, turning functional code references into localized text that breaks system integration.
This ties into broader string management anti-patterns that create technical debt as teams scale their localization efforts.
The Real Cost of "Quick" AI Translation
These failures aren't edge cases — they're the predictable result of feeding structured technical files to tools designed for natural language translation. The time you save on initial translation gets multiplied by debugging crashes, fixing broken analytics, and rebuilding user trust after production failures.
The irony is that AI translation can work brilliantly for mobile apps, but not when you copy-paste raw files into ChatGPT. The solution requires format-aware translation systems that understand the structural constraints of mobile resource files while preserving the linguistic quality that makes AI translation valuable.
Teams serious about scaling their localization need workflows that handle these technical constraints without sacrificing development velocity.
What's Next
Raw LLMs break mobile resource files in predictable ways, but format-specific solutions are emerging that preserve both technical structure and translation quality. In our next post, we'll dive into the tools and techniques that let you harness AI translation power while keeping your strings.xml and Localizable.strings files functional.
The goal isn't to avoid AI translation — it's to use it correctly for mobile development workflows that actually scale.