Translation File Linter

Compare source and target JSON translation files and find missing keys, empty values, placeholder mismatches, broken ICU and HTML differences.

Flat or nested JSON in your source language


Translation keys
8
Errors
3
Warnings
3
Info
3
LanguageKeySeverityCheckDetail
degreetingerrorPlaceholder mismatchmissing {name}; unexpected {nam}
deinboxwarningLeading or trailing whitespacesource has 0/0 leading/trailing spaces, target has 0/1
decart.itemserrorInvalid ICUEXPECT_PLURAL_ARGUMENT_SELECTOR_FRAGMENT
decart.totalerrorPlaceholder mismatchmissing %s; unexpected %d
determswarningHTML tag mismatchmissing </a>, </b>, <a>
determsinfoTrailing punctuationsource ends with ".", target ends with "none"
defooterinfoTrailing punctuationsource ends with ".", target ends with "none"
debuttons.saveinfoSame as sourceTranslation is identical to the source text
debuttons.cancelwarningExtra keyKey does not exist in the source file

Runs in your browser. Files are not uploaded unless the tool says otherwise.

What the linter checks

The tool flattens both files to dot-notation keys and compares every target value against its source. Each finding has a severity so you can decide what blocks a release and what is only worth a look:

  • Errors: missing keys, empty values, placeholder mismatches ({name}, {{count}}, %s, %1$d, ${x}, %@), ICU messages that do not parse, and ICU arguments that differ between source and target.
  • Warnings: keys that exist only in the target file, HTML tags that were dropped or added, leading or trailing whitespace that differs from the source, and a different number of line breaks.
  • Info: values identical to the source (often untranslated) and trailing punctuation that does not match.

Why placeholder mismatches matter

A translated string with a renamed placeholder does not fail at build time. It fails at runtime in one language, usually as raw {nam} text on screen or as a crash when a native formatter receives fewer arguments than the format string expects. Android %1$s and iOS %@ specifiers are the classic case: a missing argument throws at runtime and only in the affected locale. Catching this before merge is far cheaper than a bug report from a user in Germany.

ICU plural and select messages

ICU messages such as {count, plural, one {# item} other {# items}} are parsed with the same parser that FormatJS uses. Unbalanced braces, a missing other clause or a translator who changedcount to anzahl are reported as errors. Languages with more plural forms than English (Polish, Russian, Arabic) are allowed to add categories; the check compares argument names, not the list of plural cases.

Running the same checks continuously

This page is a one-off check that runs entirely in your browser. SimpleLocalize runs the same family of QA checks on every translation as it is edited or auto-translated, including placeholder, ICU, HTML, whitespace, length and glossary checks, and can flag problems in the editor or fail an export. Upload your files there when you want the checks to run every time, not just today.

More translation tools

Manage translations with SimpleLocalize

  • Import the same file formats you just converted or checked
  • Auto-translate with DeepL, Google, OpenAI, Claude or Gemini using your own API keys
  • Free plan for small projects, no credit card required
Start for free
No credit card required5-minute setup