</>
← Back to blog
Dev 2026-08-07 7 min read

Catching Missing Translation Keys and Interpolation Mismatches Before Users Do

The developer's locale never has missing keys, because the developer wrote the feature against it. Missing keys only appear in the locales added later, by translators, and they show up as raw key paths rendered to real users. Comparing locale files structurally, instead of eyeballing them, is how you find these before shipping.

i18nlocalizationtranslation keysinterpolationICU MessageFormat

Internationalization bugs are unique because they are invisible to the person who introduces them. You build a feature against your own locale, which has every key, and the feature works. The bug appears only in a locale that is missing the key, which is usually a locale you do not speak and do not test in. The result is a raw key path like settings.profile.title shown to a real user, or an interpolation that renders empty because a parameter was renamed.

Why missing keys are hard to catch in review

Code review catches missing keys only if the reviewer diffs the locale files, which most reviewers do not. The feature works in the development locale, the tests pass in the development locale, and the missing key is in a file the reviewer never opens. The bug ships, and the first sign of it is a user screenshot showing a raw key path where a translated string should be.

The structural problem is that locale files grow independently. The English file gets a new key with each feature. The translator adds the corresponding key to the other locales later, or misses it. There is no compile error when a key is missing, because locale lookups fall back to the key itself. The fallback is the bug.

Comparing locales structurally

The fix is to compare locale files as nested key structures, not as text. A text diff shows which lines changed, but a missing key in a nested object is not a line change, it is an absent line. A structural comparison flattens both files to key paths and reports which paths exist in one but not the other.

The comparison has to go both directions. English may have a key that Japanese lacks, which is the obvious missing-key bug. Japanese may have a key that English lacks, which is usually a stale key left over from a removed feature. The stale key is not user-facing, but it is dead weight, and it can hide a real bug if the key name collides with a new feature later.

Interpolation parameter mismatches

A translation string with interpolation, like Hello, {name}, expects a parameter called name. If the translator rewrites the string to Bonjour {prenom}, the parameter is now prenom, but the code still passes name. Depending on the i18n library, the result is an empty string, a literal {name}, or a runtime error.

This class of bug is harder to catch than missing keys because the key exists in both locales. A structural key comparison passes. The mismatch is only in the parameters inside the string value, which requires parsing the interpolation syntax of each string and comparing the parameter sets.

ICU MessageFormat makes this stricter, because it adds {count, plural, one {...} other {...}} constructs where the parameter name appears multiple times and the library validates the count. A translated plural that drops the count parameter, or renames it, breaks at runtime. Detecting this means parsing the ICU syntax, not just grepping for braces.

Nested objects versus flat keys

Locale files come in two shapes: nested objects, where settings.profile.title is settings: { profile: { title: ... } }, and flat keys, where the same string is a single key settings.profile.title. The comparison tool has to handle both, because projects mix them. A flat-key file compared against a nested file is a common source of false positives if the tool only handles one shape.

The deeper issue is key collision across the two shapes. A flat file with a key settings.profile and a nested file with settings: { profile: ... } look different in text but may resolve to the same lookup path depending on the library. Normalizing both to a canonical path list before comparing avoids this.

When to run the check

Run the comparison whenever a locale file changes, which in practice means on every pull request that touches translations. The check is fast, it is deterministic, and it catches a class of bug that is otherwise invisible until a user reports it. Running it in CI, not just locally, means a translator's missing key is caught before merge, not after release.

The comparison is also useful when adding a new locale. Pasting the new locale file and the reference locale file into the tool gives an immediate list of what the new locale is missing, which is the starting checklist for the translator.

What the comparison will not catch

A missing key is objective. A wrong translation is not. The comparison cannot tell you whether a translation is accurate, only whether the keys and parameters match. A locale with every key present and every parameter matched can still have a completely wrong translation, and that is a problem for a bilingual reviewer, not a diffing tool.

The comparison also cannot catch cultural issues, like a date format that is technically correct but reads oddly, or a string that is too long for the layout it appears in. These need human review against the actual UI. The tool catches the mechanical bugs, the missing keys and the parameter mismatches, so the human review can focus on the ones that require judgment.

The i18n tool on this site runs the structural comparison and the parameter check in the browser, so you can paste two locale files and get the diff without sending them anywhere. It is the check that should run before every translation merge.

Primary references

Standards and official documentation used to check the technical details in this guide.

Find missing keys and param mismatches locally

The i18n tool on this site compares locale JSON files, lists missing keys in each direction, and flags interpolation parameter mismatches. Runs in the browser, so your locale files stay on your machine.

Open the i18n tool

Related guides

Continue with practical guides from the same topic area.

View all guides

Cookie Consent

We use cookies to enhance your experience and show relevant ads. You can customize your preferences.