Skip to content

UI strings

Designed for any JS/TS project that uses i18next: React apps, Next.js (client and server components), Node.js services, Plain HTML, Astro websites and CLI tools.

Which guide to read

Your appRead next
React / Next.js / Node + i18nextWire i18next (Step 4)
Plain HTML (no t() in markup)Plain HTML apps
Astro marketing site (hybrid)Astro website
t() rules, interpolation, pluralst() calls & plurals
Language picker / RTLLanguage switcher & RTL
Runtime API signaturesRuntime helpers

Step 1: Initialise

bash
ai-i18n-tools init [-P <provider>]

This writes ai-i18n-tools.config.json with the ui-markdown template (including a default provider / providers block). Before running translate-ui or sync, set the API key for your active provider in the environment or .env — Ollama excepted; see Provider and API key. Edit the config to set:

  • provider and providers — at least one provider with translationModels; change the preset or model list if the default is not your choice (init -P <provider>). See LLM providers and models.
  • sourceLocale - your source language BCP-47 code (e.g. "en-GB"). Must match SOURCE_LOCALE exported from your runtime i18n setup file (src/i18n.ts / src/i18n.js).
  • targetLocales - array of BCP-47 codes for your target languages (e.g. ["de", "fr", "pt-BR"]). Run generate-ui-languages to create the ui-languages.json manifest from this list.
  • ui.sourceRoots - directories or glob patterns to scan for t("…") calls (e.g. ["src/"], ["src/**/*.ts"]).
  • ui.stringsJson - where to write the master catalog (e.g. "src/locales/strings.json").
  • ui.flatOutputDir - where to write de.json, pt-BR.json, etc. (e.g. "src/locales/").
  • providers.<active>.uiModels (optional) - ordered UI-only model list for translate-ui, plural generation, and proofread-ui (after any matching localeModels entry, before translationModels). See Providers and models.

Step 2: Extract strings

bash
ai-i18n-tools extract

Scans all JS/TS files under ui.sourceRoots for t("literal") and i18n.t("literal") calls. Writes (or merges into) ui.stringsJson.

The scanner is configurable: add custom function names via ui.uiExtractor.funcNames (or legacy ui.reactExtractor.funcNames). For Astro pages and components, add .astro to ui.uiExtractor.extensions. For plain HTML, see Plain HTML apps.

Step 3: Translate UI strings

bash
ai-i18n-tools translate-ui

Reads strings.json, sends batches to the active LLM provider for each target locale, writes flat JSON files (de.json, fr.json, etc.) to ui.flatOutputDir. Model selection uses the UI chain: localeModels(locale)uiModelstranslationModels (see Providers and models).

Per-locale model overrides

Depending on the target language, some translation models may perform significantly better than others—for example, qwen and z-ai models tend to produce higher quality translations for Asian languages compared to many Western (Occidental) language models. To take advantage of this, you can use optional providers.<active>.localeModels entries to specify a prioritized list of models for each BCP-47 locale. These model lists are tried before the more general uiModels and translationModels for that particular locale. This allows you to tailor model selection and achieve better translation quality per language. Locale tags are matched case-insensitively (so zh-cn and ZH-CN are equivalent). If no custom entry matches a locale, the tool falls back to the default uiModels and translationModels order for UI translations. The same localeModels mechanism also applies to document, JSON, and SVG translation.

Translations database (strings.json)

For each entry, translate-ui stores the model id from the active provider that successfully translated each locale in an optional models object (same locale keys as translated). Strings edited in the Translation Dashboard are marked with the sentinel value user-edited in models for that locale. The per-locale flat files under ui.flatOutputDir remain source string → translation only; they do not include models (so runtime bundles stay unchanged).

Note: Dashboard edits to UI strings live in strings.json, not the SQLite documentation cache. Run plain sync or translate-ui (no special flag) to rewrite flat locale files from the catalog — --force-update is not forwarded to the UI step. Avoid --force on UI commands after manual edits: it re-translates every entry and can overwrite your user-edited rows.

Then wire i18next at runtime — Wire i18next.

Exporting to XLIFF 2.0 (optional)

To hand UI strings off to a translation vendor, TMS, or CAT tool, export the catalog as XLIFF 2.0 (one file per target locale). This command is read-only: it does not modify strings.json or call any API.

bash
ai-i18n-tools export-ui-xliff

By default, files are written next to ui.stringsJson, named like strings.de.xliff, strings.pt-BR.xliff (basename of your catalog + locale + .xliff). Use -o / --output-dir to write elsewhere. Existing translations from strings.json appear in <target>; missing locales use state="initial" with no <target> so tools can fill them in. Use --untranslated-only to export only units that still need a translation for each locale (useful for vendor batches). --dry-run prints paths without writing files.

Released under the MIT License.