· 4 min read
How to Find Missing Translation Keys
Manesh Jayawardhana
CIO & Co-founder
The German build crashes on the checkout page. The English one is fine, and the code is identical.
The German translation of checkout.greeting dropped the {name} placeholder that the code passes. In most i18n libraries that is an error at render time, not a cosmetic problem, and it only appears in one locale.
Three findings, very different severities
Comparing a base locale against a target produces three categories, and treating them equally wastes time on the harmless one.
Placeholder mismatch — breaks at runtime. A translation missing a placeholder the code supplies, or containing one the code does not, throws or renders a literal {name} depending on the library. This is a bug, it is locale-specific, and it will not be caught by any test that runs in the default language.
Missing key — degrades. Most frameworks fall back to the base language. The interface shows English in the middle of German, which looks unfinished and works. Some frameworks render the raw key instead, which looks broken.
Extra key — harmless. A key in the translation with no counterpart in the base. Almost always a leftover from a removed feature. Worth cleaning up so future reviews are shorter, and not urgent.
| Finding | Runtime effect | Priority |
|---|---|---|
| Placeholder mismatch | Throws or renders literally | Fix first |
| Missing key | Falls back or shows the key | Fix before release |
| Extra key | None | Clean up eventually |
Pluralisation is where this gets harder
English has two plural forms — one and many. Many languages have more, and some have fewer.
Arabic has six plural categories. Polish and Russian have distinct forms depending on the final digits of the number. Japanese and Chinese frequently have one.
A translation file that provides the English one-and-other structure for a language needing six is not missing a key in any way a simple comparison detects — the key exists, and it is inadequate. Frameworks using ICU MessageFormat handle this properly, and a coverage check has to understand the plural categories to report on it.
That is worth knowing when a comparison reports full coverage and the Polish build still reads wrongly for certain numbers.
What to do about the fallback
Deciding what happens on a missing key is a product decision, not a technical default.
Fall back to the base language. Acceptable in a mostly-translated interface. Jarring if half the page is in the wrong language.
Render the key. Never acceptable in production, and useful in development because it makes gaps obvious.
Fail the build. The strictest option and the one that guarantees no gaps ship. It means translation completion blocks release, which is a real constraint and sometimes the right one.
Most teams end up with the key visible in development, fallback in production, and a coverage check in CI that warns rather than blocks.
Text expansion breaks layouts
Coverage is a data problem. The visible failures are usually a layout problem.
Translated text is frequently longer than the English source — German and Finnish notably so, sometimes by a third or more. A button sized to fit “Save” does not fit its German equivalent, and the text truncates, wraps awkwardly, or overflows.
That is invisible in a coverage check, which sees a key present and correct.
Two defences: design components to accommodate expansion rather than sizing to the English string, and review the interface in the longest language you support rather than only in the source. Pseudo-localisation — replacing strings with artificially lengthened placeholder text — catches it during development without waiting for real translations.
Common mistakes to avoid
- Treating a missing key and a placeholder mismatch as the same severity.
- Testing only in the default locale, where neither problem appears.
- Assuming full key coverage means correct translation, when pluralisation may still be wrong.
- Leaving unused keys indefinitely, which makes every translation review longer.
- Hard-coding a string rather than adding a key, which is invisible to any coverage check.
How to do it with i18n Key Coverage Checker
The i18n Key Coverage Checker compares locale files in the browser.
- Paste the base locale and the one being checked.
- Fix placeholder mismatches first — those are the ones that break.
- Fill missing keys before release, according to what your fallback does.
- Remove the extra keys so the next review is shorter.
Other developer tools are in the tools directory.
Frequently asked questions
Why do placeholder mismatches matter most?
Because a missing key usually falls back to the base language and still works. A translation missing a placeholder the code passes throws at render time in many libraries, and only in that locale.
What about keys only the translation has?
Usually leftovers from removed features. Harmless, and worth removing so future translation reviews are shorter and coverage figures are honest.
Does full key coverage mean the translation is correct?
No. Languages with more plural categories than English can have every key present and still read wrongly for certain numbers, which a simple key comparison does not detect.
Final thought
Sort the findings by whether they throw. A missing key is a cosmetic problem you can ship; a placeholder mismatch is a crash in one language.