JSON
Designed for projects that keep UI copy in nested JSON files per locale (for example src/i18n/en/translation.json) instead of t("…") in source. The CLI walks string values in those files, translates them via the active LLM provider, and writes per-locale outputs using json[].outputPathTemplate. It uses the same SQLite cache as translate-docs and translate-svg (cacheDir).
This pipeline does not run extract — there is no strings.json catalog. Enable it with features.translateJson and one or more entries in top-level json[].
Per-locale model overrides
translate-json resolves models per target locale: localeModels(locale) first when configured, then translationModels. Use this for nested JSON bundles where certain locales benefit from dedicated models — for example zh-Hans / zh-Hant theme files. See Providers and models.
Step 1: Initialise for nested JSON
ai-i18n-tools init -t ui-json-bundles [-P <provider>]That template sets features.translateJson: true, disables UI extraction and document translation, and scaffolds a single json[] block pointing at src/i18n/en/translation.json with output src/i18n/{llocale}/translation.json. It also includes a default provider / providers block (openrouter unless you pass -P <provider>) — set the matching API key (or use local Ollama) before running translate-json or sync; see Provider and API key. Edit sourceLocale, targetLocales, contentPaths, and outputPathTemplate for your repo layout.
Step 2: Configure json[]
Each json[] block describes one pipeline:
contentPaths— one or more.jsonfiles, directories, or globs (for example"src/i18n/en/translation.json"or"src/i18n/en/overrides/*.json"). Paths are resolved from the project root.outputPathTemplate— required. Where to write each target locale file. Placeholders:{locale},{LOCALE},{llocale}(lowercased locale, useful for Astro route folders),{stem},{basename},{extension},{relativeToSourceRoot}.targetLocales(optional) — subset for this block only; otherwise roottargetLocalesapplies.keyPolicy— which JSON keys hold translatable prose vs stable identifiers (see below).description(optional) — shown in CLI headers andstatusoutput.
Example (multiple source files, lowercase locale folders):
{
"sourceLocale": "en",
"targetLocales": ["de", "fr", "pt-BR"],
"features": {
"translateJson": true
},
"cacheDir": ".translation-cache",
"json": [
{
"description": "App UI bundle",
"contentPaths": [
"src/i18n/en/translation.json",
"src/i18n/en/overrides/*.json"
],
"outputPathTemplate": "src/i18n/{llocale}/{basename}",
"keyPolicy": {
"mode": "denylist",
"skipKeys": ["id", "slug", "href", "url", "key", "code"],
"translateKeys": []
}
}
]
}keyPolicy
mode | Behaviour |
|---|---|
allowlist | Only keys matching translateKeys (dot paths; minimatch globs) are translated. |
denylist | Translate all string values except keys matching skipKeys. |
both | Apply translateKeys first, then remove matches from skipKeys. |
Paths use dot notation (nav.home.label). A bare name like slug matches the final key segment at any depth.
Step 3: Translate JSON bundles
ai-i18n-tools translate-jsonOptional flags (same ideas as translate-docs): -l / --locale for a subset of targets, -p / --path to limit files, --dry-run, --force (clear file tracking and segment cache for matched files), --force-update (re-process when file hash matches; segment cache still applies), -b / --batch-concurrency, --prompt-format (xml | json-array | json-object).
JSON-only projects can run:
ai-i18n-tools sync --no-ui --no-svg --no-docsWhen UI or docs are also enabled, sync runs translate-json after translate-docs (unless --no-json). Skip JSON with --no-json.
Check coverage per file and locale:
ai-i18n-tools statusWhen translateJson is on, status prints a json[] section (✓ up to date, ● stale or missing).
JSON vs other pipelines
| Situation | Use |
|---|---|
UI strings in t("…") / i18n.t("…") in JS/TS/Astro | UI strings — extract + translate-ui |
Docusaurus write-translations catalog ({ "key": { "message": "…", "description": "…" } }) | Documents — docs[].docusaurusCatalogDir + translate-docs, not json[] |
| VitePress theme/nav/sidebar strings | Documents — docsOutput.vitepressThemeCatalog + translate-docs; do not use json[] — see VitePress integration |
Nextra _meta.ts labels and theme dictionary .ts | Documents — translate-docs (auto _meta when style: "nextra", optional nextraDictionaryPath); do not use json[] — see Nextra integration |
Fumadocs meta.json labels and UI overrides catalog | Documents — translate-docs (auto meta.json when style: "fumadocs", optional fumadocsUiCatalog); do not use json[] — see Fumadocs integration |
Standalone nested locale JSON (ZenBrowser-style translation.json trees) | JSON — json[] + translate-json |
Illustrated .svg files with <text> / <title> / <desc> | features.translateSVG + svg + translate-svg (optional; not one of the three main pipelines) |
Field reference: json in Configuration reference. Cache keys for cleanup use json-block:{blockIndex}:{projectRelPath} in file_tracking.