One character in a placeholder breaks the substitution
A translated placeholder differs from the source by a letter or a space, so the interpolation does not bind and the raw token reaches the user.
What you see
- •The literal `{{max}}` or `%@` appears on screen in one language.
- •The translation is otherwise perfect, which is why review misses it — the eye reads the sentence, not the token.
- •Often a single character: a transposed letter, a space inside the braces, a doubled symbol.
Why it happens
Interpolation is an exact string match. `{{max}}` and `{{mix}}` are different variables as far as the runtime is concerned, and one of them does not exist, so the token is left in the output. The same applies to `% @` versus `%@`, or `%1$$lld` versus `%1$lld`. These are typing accidents that no spell-checker flags and no key comparison can see.
1A transposed or mistyped variable name
The classic one-character case: the sentence is right, the variable is not, and the message renders with a token in the middle of it.
Spanish had `{{mix}}` where the source defines `{{max}}` in the prompt-too-long error. We filed it as an issue; a contributor fixed the typo and added a placeholder-parity test suite covering every locale, so the next one fails CI.
Our report — the issue produced a permanent test, not just a string fix →
2Whitespace or punctuation inside the token
A space added inside a specifier while editing, or a symbol doubled, is enough. It is invisible in a review diff rendered with proportional fonts.
ACINQ/phoenix1.1k★
Czech rendered `**% @ **` instead of `%@`, and nineteen Arabic strings carry doubled or tripled dollar signs such as `%1$$lld`.
Find every instance
A typo shows up as one placeholder missing and another unexpected on the same key, which is the signature to look for:
npx @shipi18n/cli@latest check ./locales -s en --severity 'missing-key=off,untranslated=off,orphan-key=off'When you see `placeholder-missing` and `placeholder-added` reported together on one string, it is almost always a misspelling rather than two separate mistakes.
✗ es coverage 100.0% 1 error(s), 1 warning(s)
error chat.errors.promptTooLong placeholder-missing — dropped {{max}}
warning chat.errors.promptTooLong placeholder-added — unexpected {{mix}}How to fix it
- 1Copy the token from the source string rather than retyping it, including its braces, dollars and spacing.
- 2Fix the whole family at once: a typo introduced during one editing pass is usually repeated in neighbouring strings.
- 3Add a parity test or the CI check, which is what the Excalidraw contributor did — it turns a one-off fix into a permanent guarantee.
The rules that catch this
How often this actually happens
Every finding on our scoreboard was read against its source string by hand before being filed: https://shipi18n.com/oss