Translation Maintenance Workflow
For general documentation commands (build, deploy, screenshots, README generation), see Documentation Tools.
Overview
The documentation uses Docusaurus i18n with English as the default locale. Source documentation lives in docs/; translations are written under i18n/{locale}/. Supported locales: en-GB (default), fr, de, es, pt-BR, hi, zh-Hans.
AI translation for the app UI, Docusaurus markdown/JSON, SVG assets, and default notification templates is handled by ai-i18n-tools from the repository root, configured in ai-i18n-tools.config.json (not inside documentation/). Set OPENROUTER_API_KEY when running translate commands.
To try an unpublished checkout on the same machine (default ../ai-i18n-tools), switch the dependency with pnpm i18n:tools --local or ./scripts/link-ai-i18n-tools.sh --local. That links both the CLI (pnpm i18n:*) and the ai-i18n-tools/runtime import. Rebuild the tools package after source changes (pnpm build in that checkout). Restore the latest npm package with --remote. Do not commit the link: specifier.
When English documentation changes
- Edit source in
documentation/docs/(English only). Landing-page copy isdocumentation/src/landing/landing.html. - Docusaurus UI strings (theme labels, navbar, etc.): if needed, run
pnpm write-translationsindocumentation/soi18n/en/*.jsonpicks up new keys. - Heading IDs:
pnpm write-heading-ids(fromdocumentation/). - Translate from the repo root (or use the shortcuts below from
documentation/):pnpm i18n:extract— refreshsrc/locales/strings.jsonfromt('…')in the Next.js app.pnpm i18n:translate:docs— translate markdown, Docusaurus shell JSON, and the landing HTML intodocumentation/i18n/anddocumentation/src/landing/i18n/per config.pnpm i18n:translate:svg— translate SVGs underdocumentation/static/imgas configured.pnpm i18n:translate:json— translate default notification templates insrc/locales/templates/fromen-GB.json.- Or run everything:
pnpm i18n:translate.
- Build:
cd documentation && pnpm build(all locales).
From inside documentation/, the same flows are wired as pnpm translate → root i18n:translate, plus pnpm translate:docs, translate:ui, translate:svg, translate:status, i18n:extract, i18n:sync.
UI plurals
Cardinal plurals in the Next.js app use ai-i18n-tools, not hand-written _one / _other keys.
Write one English source string (usually the plural) and pass a plain object literal with plurals: true and a numeric count:
t("{{count}} backups selected", { plurals: true, count: selectedBackups.size })
Rules:
- Do not use
item(s)hedges orcount === 1 ? t('…') : t('…')pairs. - Independent numeric counts need separate
t()calls — one plural axis cannot flex two numbers (for example 1 successful and 2 failed). Concatenate the fragments:
`${t("Tested {{count}} connections:", { plurals: true, count: total })} ` +
`${t("{{count}} successful,", { plurals: true, count: successCount })} ` +
`${t("{{count}} failed", { plurals: true, count: failureCount })}`
- Non-numeric interpolations (names, labels, etc.) are fine in the same plural string as
{{count}}. pnpm i18n:extractmarks the catalog row"plural": true.pnpm i18n:translate:uifills CLDR forms and writessrc/locales/en-GB.json(plural keys only).src/i18n.tsandsrc/lib/i18n-server.tsload that file assourcePluralFlatBundleso English singular/plural resolve at runtime.
Default notification templates
Settings → Templates → Reset loads defaults from src/locales/templates/{locale}.json (wired in src/lib/default-notification-templates.ts).
- Edit
src/locales/templates/en-GB.jsononly (English source). - Run
pnpm i18n:translate:json(orpnpm i18n:translate) from the repo root. - Review diffs — placeholders such as
{backup_name}and{problem_table}must stay unchanged;priorityandtagsare skipped bykeyPolicyinai-i18n-tools.config.json. - Run
pnpm i18n:statusto see JSON block coverage.
See the ai-i18n-tools JSON guide for flags (--locale, --force, etc.).
Landing page HTML
The docs homepage body is a single English HTML file, not React section components.
- Edit
documentation/src/landing/landing.html(anddocumentation/src/landing/landing.cssfor layout). Keep the hash idsfeatures,dashboard,workflow,security, andinstall. - Run
pnpm i18n:translate:docsfrom the repo root (orpnpm translate:docsfromdocumentation/). - Generated copies are written to
documentation/src/landing/i18n/{locale}/landing.html. Do not edit those files by hand.
translate-docs uses the HTML pages pipeline: visible text and alt / title / aria-label are translated; <pre> and <code> stay in English. Navbar labels and the page title stay in Docusaurus Translate (homepage.nav.*, homepage.meta.*).
Do not add data-i18n markers to this file, and do not list it under ui.sourceRoots. The same HTML file must not be in both the documents pipeline and the UI-strings pipeline.
Glossary
- UI terminology for documentation comes from each
ui[]catalog withuiGlossaryleft on (the default). The Next.js app catalog issrc/locales/strings.json(produced bypnpm i18n:extract). Do not setglossary.uiGlossary; that key is rejected. - Overrides live in
documentation/glossary-user.csv(glossary.userGlossaryin config). See the ai-i18n-tools glossary docs for column format. - Generate a CSV template:
pnpm i18n:glossary-generate(root).
Cache
Translation cache for ai-i18n-tools is under .translation-cache/ at the repo root (cacheDir in ai-i18n-tools.config.json). It is gitignored. Use pnpm i18n:status and the CLI’s --force / cache flags per ai-i18n-tools documentation when you need a full refresh.
Heading IDs and anchors
Use explicit IDs so links stay stable across languages. Prefer the MDX comment syntax (pnpm write-heading-ids uses --syntax mdx-comment):
## This is a heading {/* #this-is-a-heading */}
Put IDs on h2 and below. Docusaurus write-heading-ids skips h1 (the page/sidebar title). documentation/docusaurus.config.ts also strips heading-id comments from inferred titles, because Docusaurus metadata extraction still only removes classic {#id}.
cd documentation
pnpm write-heading-ids
Ignore lists
Use .translate-ignore at the repo root (same idea as .gitignore) for paths the doc translator should skip, if you add one for your workflow.
Docusaurus theme JSON
pnpm write-translations extracts Docusaurus UI strings into documentation/i18n/en/. The ai-i18n-tools translate-docs step (with markdownOutput.style: "docusaurus") fills translated JSON under each locale alongside markdown, per ai-i18n-tools.config.json.
Troubleshooting
OPENROUTER_API_KEYnot set — export it or add to.env.localat the repo root.- Model / quality — adjust
openrouter.translationModelsand related options inai-i18n-tools.config.json. - Glossary — edit
documentation/glossary-user.csvor regenerate UI strings and re-run extract + translate.
Adding a new language
- Add the locale to Docusaurus
i18n.localesandlocaleConfigsindocumentation/docusaurus.config.ts. - Add the same locale to
targetLocalesinai-i18n-tools.config.json(repo root). - Run
pnpm i18n:generate-ui-languagesat the root, thenpnpm i18n:extract/ translate commands as needed.