JSON
JSON (flat) and JSON (nested): string maps with dotted or nested keys, for i18next, react-intl, next-intl, Vue I18n and most JavaScript stacks.
| Format | Identifier | Extension |
|---|---|---|
| JSON (flat) | json_flat | .json |
| JSON (nested) | json_nested | .json |
Laravel's lang/{locale}.json files use the same flat shape under their own identifier, laravel_json. See Laravel.
JSON (flat)
A single object of string values. The key is the property name, dots and all.
{
"home.title": "Welcome back",
"home.greeting": "Hello, {name}!",
"cart.items_one": "{count} item",
"cart.items_other": "{count} items"
}- Every value must be a string. A number, boolean or
nullis an import error. - A value that is an object or array is an error:
Key "home" holds a nested group, which the JSON (flat) format cannot read. This file needs JSON (nested).
JSON (nested)
Objects nest to any depth. On import, the path to each string is joined with . to form the key; on export, keys are split on . to rebuild the objects.
{
"home": {
"title": "Welcome back",
"greeting": "Hello, {name}!"
},
"cart": {
"items_one": "{count} item",
"items_other": "{count} items"
}
}This file imports the keys home.title, home.greeting, cart.items_one and cart.items_other.
- Every leaf must be a string.
- Arrays are read like objects whose keys are the indexes (
steps.0,steps.1), and are written back as objects with those keys, not as arrays. - A property name that contains a dot is joined like any other segment, so
{"a.b": {"c": "x"}}imports asa.b.cand exports as{"a": {"b": {"c": "x"}}}. - If two paths flatten to the same key (
{"a.b": "x", "a": {"b": "y"}}), the import fails with a duplicate-key error. - A project where one key is a prefix of another (
homeandhome.title) cannot be exported as nested JSON. See Keys.
Plurals
Neither JSON format has a plural construct. You have two options:
- Suffix keys, as i18next does (
items_one,items_other). transglot stores each as an ordinary key, so each suffix is translated separately. Add the suffixes the target language needs (items_few,items_many) as keys of their own. - ICU messages in a value, as react-intl and next-intl expect:
"{count, plural, one {# item} other {# items}}". The whole message is one string.
Plural keys you create in transglot (with one form per category) are not written to JSON: an export leaves them out and counts them. Use Flutter ARB, Android XML or a spreadsheet to carry them, or publish flutter_arb for the runtime SDKs.
Placeholders
Values are read and written exactly as they are, so {name}, {{name}}, %s and ICU arguments survive a round trip. See Placeholders.
Export
Exports are UTF-8 with two-space indentation, keys in byte order, non-ASCII characters and slashes written as themselves rather than escaped, and one trailing newline. Untranslated keys are left out.
JSON has no place for descriptions; keep them in the console.