Localization release QA

i18n JSON key parity: exact paths and translation boundaries

Key parity is a structural review, not proof that a translation is correct, complete or suitable for its screen. Use a source dictionary and one target dictionary to make missing work visible before release.

Content updated: · Maintained by Hung Chi-Hsueh · corrections

Stress-test layouts before translation

Generate a test-only pseudo locale from a small source string dictionary, then load it into your app and inspect narrow screens, buttons and errors. Accents and padding make some clipping visible; unmarked text may be hardcoded or intentionally excluded. This is not a real translation or proof of locale readiness.

The generator protects only its listed simple placeholders and inline markup. Complex ICU messages and ambiguous input are rejected; use your runtime's message-aware tools for those branches. Verify all generated strings with the actual formatter before adding them to a test build.

Literal keys are not framework aliases

The literal member "a.b" has JSON Pointer /a.b. A nested object a containing b has pointer /a/b. Both can coexist. This checker never collapses them, changes case, trims keys or normalizes Unicode. Empty member names, slash and tilde are preserved; JSON Pointer escapes ~ as ~0 and / as ~1.

Some frameworks configure key separators or resolve dotted and nested keys as aliases. This tool compares the actual JSON structure only. Displayed pointers are JSON strings: newline and invisible or bidirectional controls are escaped so a key cannot masquerade as a different path.

Read each category without a misleading completion score

Missing and extra entries refer to string-leaf paths. A string-versus-object conflict is reported once at the conflicting path, not again for every descendant. Empty nested objects are namespace reminders, not translated messages. Empty root dictionaries contain no strings to compare.

A string is blank when JavaScript trim() leaves no characters; the source is never changed. Zero-width joiners are not automatically stripped. Matching text such as OK or a brand name is not labeled untranslated. Source-side blanks also need review. Category counts are review items, not a translation-completion percentage.

Plurals, fallback and placeholders still need runtime tests

Languages can legitimately require different plural categories. i18next also supports configurable interpolation, nested resources, objects and arrays. This checker deliberately accepts only root objects whose members are namespace objects or strings. Arrays, null, numbers and booleans are refused with the side and pointer; it does not claim full i18next or ICU compatibility.

Extra keys may be intentional, and a missing source key might be supplied by your runtime fallback. Neither outcome authorizes automatic deletion or guarantees that a screen works. Interpolation variables, ICU messages, HTML placeholders, copy freshness, translation accuracy and text overflow require separate framework tests and human review.

Compare message tokens separately

Use the translation token checker on one source and target message. Token mode reports occurrence differences for common placeholders, printf tokens, tags, numbers, URLs, email candidates and line breaks; its HTML check compares tag names and opening or closing occurrences, not attributes or nesting. A difference is a prompt for human review, not proof of an error.

ICU mode parses plural and select messages and compares argument-name sets; it does not compare branch coverage or meanings. Test real messages with the target framework and locales. Inputs remain local; exported reports can include token values.

Strict inputs, complete reports and local privacy

Each UTF-8 input is limited to 1 MiB, 100 levels, 50,000 nodes and 20,000 string entries. Duplicate decoded keys and invalid Unicode are refused. One initial BOM is removed with a notice; extra BOMs and invalid UTF-8 bytes are not repaired. Pointers are limited to 4096 UTF-8 bytes. A five-second Worker deadline, cancellation and source changes discard stale work without a partial report.

The table pages through 100 issues at a time. The complete value-free JSON report includes every category regardless of the current filter, up to 8 MiB. Copying missing paths is limited to 1 MiB; larger lists require downloading the complete report. Row previews show at most 1000 characters and do not alter the original. Viewing values does not add them to the report.

Inputs remain in browser memory: no upload, URL state, persistent storage or content in tool analytics. Reports omit values and filenames, but key names can expose unreleased product structure. Review before sharing. Local processing does not protect against compromised devices or browser extensions, and clearing the page is not a secure-memory-erasure guarantee.

Example
Source: {"a.b":"Flat","a":{"b":"Nested"}}
Target: {"a.b":"字面"}
Missing pointer: /a/b
Matched pointer: /a.b
Neither path is renamed or merged.

Data provenance

Sources