How placeholders break in translation: a failure catalog
A placeholder token like {playerName} is not decorative text — it is a contract between the source string and the code that formats it at runtime. Translation, as a process, treats every string as prose to be rewritten, and prose-rewriting is exactly what breaks a token that has to match its source character-for-character. This article catalogs the concrete ways that happens, all of which look identical to normal, correct translation until the moment the runtime tries to fill in the token.
Placeholder deleted
A translator rewrites a sentence for natural flow and the token simply falls out of the rewrite: You have {itemCount} items becomes 持っているアイテムです with no count anywhere. The runtime has nothing to substitute into, so either the format call throws, or — more commonly in loosely-typed template systems — it silently produces text with the count missing, which nobody notices until a player reports it.
Extra placeholder added
Less common, but real: a translator copies a token from a similar string in the same file and it ends up in the wrong one, or duplicates one that was already correct. If the target string now references an argument the code never passes, most format implementations either throw an out-of-range error or print the literal token text — {2} — directly to the player, which is one of the few failures in this list that is immediately visible on screen.
Case changed: {playerName} to {playername}
Autocomplete, spellcheckers, and sentence-case habits in some languages will happily lowercase the first letter of a token sitting at the start of a sentence. Named placeholders are usually looked up by exact key match, so {playername} does not resolve to the same value as {playerName} — it is a different, undefined key as far as the runtime is concerned.
Fullwidth characters replacing ASCII braces
This one is specific to CJK input but common: a translator typing in a Japanese or Chinese input method can produce a fullwidth brace ({playerName}) instead of the ASCII { and } the format parser expects. Visually, in most fonts, the fullwidth and halfwidth brace are close enough to pass a casual read. To the parser they are different Unicode code points, so the token is not recognized as a placeholder at all — it's printed as literal text, braces and all.
Positional reordering the runtime does not support
Plain %s or {0}-without-explicit-index systems fill arguments strictly in call order. A translator who reorders the sentence for target-language grammar — putting the second argument before the first — changes which value lands in which slot, without the runtime knowing anything moved. The result is grammatically fine text with the wrong number, name, or item swapped in.
%s dealt %d damage -> %d damage dealt by %s (values now swapped)
Spacing inside braces
{ playerName } instead of {playerName} looks harmless, but most parsers match placeholder keys by exact string, whitespace included. A stray space, often introduced by autoformatting in a spreadsheet or an editor's word-wrap, is enough to make the key lookup fail silently.
Why every one of these is mechanically detectable
None of these failures require understanding what the sentence means. Each one is a structural mismatch between the placeholder tokens present in the source string and the tokens present in the target string — a set comparison, not a linguistic judgment. That's precisely what makes this category of bug worth automating: a script can extract every token from source and target with a regular expression, diff the two sets, and flag deletions, additions, case mismatches, and fullwidth substitutions without ever needing to know what language the target is in.
- Deleted token: present in source, absent in target
- Extra token: present in target, absent in source
- Case or spelling drift: token exists in target but the exact key differs
- Fullwidth substitution: token exists visually but uses different Unicode code points
- Spacing drift: token exists but with extra internal whitespace