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.
$49 once · No email · Full app for 14 days

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
Verification
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.
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.
Interpolation 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.
Plural 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, many and other. 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.
Invalid ICU
If you use ICU messages through i18next-icu, they are parsed and validated: unmatched braces, a plural missing other, a malformed select. Unlike Flutter, the i18next ICU runtime does substitute #, so a bare # is left alone here rather than flagged.
Same 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.
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.
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.
FAQ
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. On save they are written back as suffixed keys.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?
Price
One purchase, no subscription
$49once
Early-adopter price. Full price after launch is $79.
- All five formats, not just this one
- Live validation while you edit
- AI fill with your own API key, or a local model
- macOS, Windows and Linux
- Updates within the major version
The comparison worth making is against a cloud TMS seat rather than against another editor. Lokalise lists $144 a month at entry and $999 a month on its Advanced plan, checked July 2026. That bill arrives every month. This one does not.
Docs
Read before you download
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.
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 editor