i18next JSON · macOS, WINDOWS, LINUX
An i18next JSON editor that keeps your nesting
StringLane opens every locale JSON in your project at once, shows nested keys as readable dot paths, and compares {{variable}} interpolation across languages. Files are written back nested exactly as you had them.
For macOS, Windows and Linux14-day trial, no email · $49 once

A renamed {{plano}}, flagged on the cell
THE FORMAT
What StringLane opens
i18next keeps one JSON file per language, usually under a folder named for the locale, and lets you nest keys as deeply as you like. Nesting is good for organisation and bad for comparison: a key three levels down in one file is hard to line up against five other files. StringLane flattens the view to a dot path and leaves the file itself nested.
- File layout
- One JSON file per language,
locales/en/translation.json - Nesting
settings.account.titleshown as one row, stored nested- Placeholders
{{variable}}, compared between locales by name- Plurals
- CLDR suffix keys such as
itemCount_oneanditemCount_other - ICU
- Validated, and
#inside a plural branch is supported here - Project chip
JSON
WHAT GETS FLAGGED
What gets flagged in an i18next project
Validation runs when the project loads and again after every edit. i18next is one of the two formats where both the ICU and the plural checks apply. The same checks run from the terminal with stringlane check, and over MCP for a coding agent.
Missing or empty per language
The key exists in your base language and is absent or blank in another file. i18next falls back at run time, so the string still renders, in the wrong language, and nothing in your build says so.
missing_keyInterpolation mismatch
{{variable}}names are compared as a set rather than by count, so a translation that renamed{{name}}to{{nombre}}is flagged, and so is one that dropped it entirely. Renaming an interpolation variable is the failure that reaches production, because the JSON stays valid.format_placeholder_mismatchPlural coverage against CLDR
Keys ending in a CLDR suffix are grouped into one row, and each language is checked against the categories it actually requires. Ukrainian needs
one,few,manyandother. English needs two. Ship the English pair for Ukrainian and the gap is flagged. Suffix matching is case insensitive, so keys left in an older casing by earlier tooling are still recognised. Ordinal keys such asplace_ordinal_oneandplace_ordinal_twoare checked against the language’s ordinal forms (1st, 2nd, 3rd in English), not its ordinary plural forms. A language that holds its own plural forms under a base value with{{count}}has each form checked against that value.missing_keyA count with no plural forms
i18next uses a key’s
_oneand_otherforms only when they exist, so a base value like{{count}} genreswith no plural forms in any language reads “1 genres”, and Russian reads “1 жанров”. It is flagged once, on the base language. A label that shows the number apart from the words, such asFound: {{count}}, is not.stringlane pluralize, the MCPpluralize_keytool and the app’s Add plural forms dialog write the base forms for you.count_without_pluralInvalid ICU
If you use ICU messages through i18next-icu, they are parsed and validated: unmatched braces, a plural missing
other, a malformedselect. Unlike Flutter, the i18next ICU runtime does substitute#, so a bare#is left alone here rather than flagged.icu_parse_errorSame as base, and guarded words
A value identical to the base language usually means it was copied rather than translated. Terms you mark as guarded are flagged when a language changes them instead.
untranslatedguarded_word_violation
What it will not do
StringLane reads the JSON files on disk. It does not run your i18next configuration, so it cannot tell you that a namespace is not registered, that a key is unreachable through your loading strategy, or that a component is calling a key that does not exist. It tells you what is missing, mismatched or malformed across the files themselves.
YOUR FILES
Your JSON comes back nested
The dot path is a view, not a transformation. StringLane never flattens your files on disk.
- Nesting structure is preserved exactly as found. A key shown as
settings.account.titleis written back three levels deep. - Key order is preserved as it appears in the file.
- Plural suffix keys are written back as
_-suffixed keys, not converted into some other plural shape. - Open the file in your editor before and after: the diff shows only the values you changed.
locales/en.json
{
"cart": {
"itemCount_one": "{{count}} item in your cart",
"itemCount_other": "{{count}} items in your cart",
"checkout": "Check out"
},
"billing": {
"plan": {
"current": "Current plan",
"upgrade": "Upgrade to {{plan}}"
}
}
}YOUR TOOLCHAIN
Where it sits in a web project
StringLane edits the same JSON your i18next setup already loads, whether that is a bundler import, a backend plugin or a static folder. It is not a plugin, it does not run at build time, and your i18next configuration does not change.
The case it is built for is the multi-format repo. If the same product ships a mobile app and a web front end, the web strings usually get checked last and least. Opening the i18next files in the same tool that opens the app strings puts them under the same missing-key view.
Let your coding agent check the same files.
The free CLI reads the same locale JSON files.
Read https://stringlane.app/docs/cli/agent-setup.md and set up StringLane for this project.Pay once for the app. The CLI is free.
Desktop app
$49once
- 14-day trial, no email, no card
- macOS, Windows and Linux
- 3 machines, updates in the major version
- Your own AI key, or a local model
Early-adopter price, $79 after launch.
CLI & agents
$0free
- Terminal, CI and MCP
- Claude Code, Cursor, Codex and 5 more
- No key, no activation
- Separate from the app licence
Lokalise starts at $144 a month (checked July 2026). StringLane sells no AI credits.
i18next JSON questions
Will it flatten my nested JSON?
How does it handle i18next plurals?
itemCount_one and itemCount_other, are grouped into a single row with one entry per quantity. Each language is then checked against the plural categories CLDR says it needs, and an _ordinal_ key against the language’s ordinal categories. On save they are written back as suffixed keys, _ordinal_ spelling included.Does it open easy_localization and slang projects?
pubspec.yaml and slang’s .i18n.json file naming. Each is then checked by its own rules: easy_localization’s {} and {name} placeholders, slang’s $name and {name}, and a nested map of plural forms as one plural key. easy_localization is not asked for few and many, which it reads only with ignorePluralRules: false.Does it understand {{variable}} interpolation?
{{count}}, or one that renamed it, is flagged as an error.What if I use ICU messages through i18next-icu?
# inside plural branches, so StringLane does not flag it here, while it does on ARB where Flutter has no pound token.Can I open my web and mobile strings in the same project?
Read before you download
i18next JSON format
Plural suffixes, interpolation, context and nesting, and what renders wrong.
Format-specific editing
What changes per format, including i18next JSON.
ICU MessageFormat explained
The syntax, and which runtimes support which parts of it.
Fixing placeholder mismatches
Reading the badge tooltip and restoring a dropped variable.
Reading validation badges
What each badge means and how to clear it.
Where key metadata is stored
A JSON locale file holds no notes, so
.stringlane/metadata.yamldoes.
ARB is the other format where ICU validation runs. If the same repo ships a Flutter app and a web front end, both open side by side in one window.
Flutter ARB editorCheck your locales tonight.
For macOS, Windows and Linux14-day trial, no email · The agent setup is free