Managing JSON translation files for web apps

Most JavaScript i18n libraries read one JSON file per language. The files are easy to write by hand and easy to let drift apart, which is where missing strings in production come from.

Flat or nested keys

Nested JSON groups keys by screen. Flat JSON writes the full path as one key, such as "checkout.pay_button". Both describe the same strings.

LocalizeMe reads either shape on import, flattening nested objects into dotted keys. It also unwraps a file whose top level is just the language code. The export is flat, so tell your library not to split keys on dots.

locales/de.json
{
  "checkout.pay_button": "Jetzt bezahlen",
  "checkout.total": "Gesamt: {{amount}}"
}

i18next and react-i18next

Turn off the key separator so a dotted key is looked up as written.

i18n.ts
i18next.init({
  keySeparator: false,
  resources: { de: { translation: de } },
})

vue-i18n

vue-i18n accepts flat messages when flatJson is on.

i18n.ts
createI18n({
  flatJson: true,
  messages: { de },
})

Pulling locale files before a build

Run the CLI as a build step and every language file matches what translators approved, with no copy-paste between tools.

terminal
localizeme init --project 42 --format json --path 'src/locales/{code}.json'
localizeme pull

Questions

Can I import nested JSON?

Yes. Nested objects are flattened into dotted keys, and a single top-level language code wrapper is removed.

Does the export keep nesting?

No. The export writes flat dotted keys. Set keySeparator to false in i18next or flatJson to true in vue-i18n.

Other guides

Unlimited strings, one flat price

LocalizeMe never counts keys, strings or languages. Try Pro free for 14 days, no card needed.