Documents
Designed primarily for markdown, MDX, and .astro documentation managed through docs[] config blocks. Each block's contentPaths field lists the files or folders to translate.
On Docusaurus sites, also set docusaurusCatalogDir to your write-translations catalog folder (e.g. docs-site/i18n/en). Then translate-docs includes shell JSON too - navbar, footer, and theme strings.
On VitePress sites, page bodies use the same docs[] pipeline. Nav, sidebar, and footer labels live in docsOutput.vitepressThemeCatalog - translate-docs bootstraps the English catalog and translates it alongside pages, no separate pipeline.
On Nextra sites, page bodies use the same docs[] pipeline with docsOutput.style: "nextra". _meta.ts sidebar labels are collected and translated automatically by translate-docs; theme dictionary strings translate via docs[].nextraDictionaryPath in the same pipeline.
On Fumadocs sites, page bodies use docsOutput.style: "fumadocs" with fumadocsParser "dot" (default) or "dir". meta.json sidebar labels are collected automatically; UI overrides translate via docsOutput.fumadocsUiCatalog.
On Astro Starlight sites, page bodies use docsOutput.style: "astro-starlight" with docsRoot at your Starlight content root (typically src/content/docs/). translate-docs writes localized markdown/MDX under src/content/docs/<locale>/ beside the English tree. Starlight ships built-in UI strings for many locales — no separate theme catalog pipeline; optional UI overrides can use jsonPathTemplate on a docs[] block for src/content/i18n/en.json.
For PNG and other raster images embedded in markdown, see Images & Screenshots. translate-docs translates alt text only; it does not copy raster files.
For an optional language switcher block in README or docs, set docsOutput.style to "flat" - see Language switcher.
SVG files are translated via translate-svg when features.translateSVG is enabled - not through docs[] / contentPaths.
Arbitrary nested UI JSON bundles unrelated to a documentation framework's shell/theme strings belong in the JSON pipeline, not in docs[].
For terminology consistency between UI and docs, set glossary.uiGlossary to your strings.json path — translate-docs reuses existing UI translations as hints in LLM prompts when matching terms appear in a segment. Optional glossary.userGlossary adds CSV overrides for product terms (shared with translate-ui and proofread-ui). Generate a starter CSV with glossary-generate, edit rows in the Translation Dashboard Glossary tab, or see Configuration — glossary and Glossary.
Per-locale model overrides
translate-docs and the docs step of sync resolve models per target locale: localeModels(locale) first when configured, then the provider's global translationModels chain. Use this when a specific language needs a different model than your default fallback list - for example, preferring Gemini for pt-BR documentation when the global chain struggles with Portuguese. See Providers and models and Configuration - localeModels.
Which guide to read
| Your setup | Start here |
|---|---|
| Docusaurus site | init -t ui-docusaurus, docsOutput.style = "docusaurus" - Docusaurus |
| VitePress site | init -t ui-vitepress + vitepressThemeCatalog for theme - VitePress |
| Nextra site | init -t ui-nextra + nextraDictionaryPath for dictionary (sidebar _meta.ts is automatic) - Nextra |
| Fumadocs site | init -t ui-fumadocs + fumadocsUiCatalog for UI (sidebar meta.json is automatic) - Fumadocs |
| Astro Starlight | init -t ui-starlight - Astro Starlight |
| Flat documents (README, changelogs, etc.) | docsOutput.style = "flat" - Output layouts, optional language switcher |
| Where translated files land | Output layouts |
Cross-page #anchor links | Anchor links |
Link and asset URL rewriting (regexAdjustments) | Link rewriting |
| Screenshots in docs | Images & Screenshots |
| Product terminology and UI/doc consistency | Configuration — glossary, Glossary |
translate-docs flags and cache | CLI options |
Step 1: Initialise for documentation
ai-i18n-tools init -t ui-docusaurus [-P <provider>]For Astro Starlight documentation sites:
ai-i18n-tools init -t ui-starlight [-P <provider>]For VitePress documentation sites:
ai-i18n-tools init -t ui-vitepress [-P <provider>]Set docsOutput.vitepressThemeCatalog for nav/sidebar/footer strings - see VitePress integration.
For Nextra documentation sites:
ai-i18n-tools init -t ui-nextra [-P <provider>]Set docs[].nextraDictionaryPath for theme dictionary strings - see Nextra integration. Sidebar _meta.ts labels are collected automatically.
For Fumadocs documentation sites:
ai-i18n-tools init -t ui-fumadocs [-P <provider>]Set docsOutput.fumadocsUiCatalog for UI overrides - see Fumadocs integration. Sidebar meta.json labels are collected automatically.
For plain Astro website UI (no Starlight):
ai-i18n-tools init -t ui-astro-website [-P <provider>]That template enables UI extraction only. For page HTML translation, also set features.translateDocs and add a docs[] block (see Astro website pages (parse-and-replace)). The examples/astro-website config shows both pipelines together.
Edit the generated ai-i18n-tools.config.json:
providerandproviders—initscaffolds a default provider block (openrouterunless you pass-P <provider>); configure at least one provider and set its API key beforetranslate-docsorsync(Ollama needs no key). See Provider and API key and LLM providers and models.sourceLocale- source language (must matchdefaultLocaleindocusaurus.config.js).targetLocales- array of BCP-47 locale codes (e.g.["de", "fr", "es"]).cacheDir- shared SQLite cache directory for all pipelines (and default log directory for--write-logs).docs- array of documentation blocks. Each block has optionaldescription,contentPaths(string or array; file, directory, or glob),outputDir, optionaldocusaurusCatalogDir,docsOutput, optionalsegmentSplitting,translateFrontmatterFields,protectAttributes,protectKeys,targetLocales,addFrontmatter, etc.docs[].description- optional short note for maintainers. When set, it appears in thetranslate-docsheadline and instatussection headers.docs[].contentPaths- markdown/MDX/.astrosources (and optionaldocusaurusCatalogDirfor Docusaurus shell JSON).docs[].outputDir- translated output root for that block.docs[].docsOutput.style-"nested"(default),"flat","doc-system", or aliases"docusaurus"/"astro-starlight"/"vitepress"/"nextra"/"fumadocs"(see Output layouts).glossary.uiGlossary- path tostrings.jsonso document segments get terminology hints from your UI catalog (see Configuration —glossary).glossary.userGlossary- optional CSV for fixed product-term translations; also used by UI pipelines and editable in the Glossary dashboard tab.
Primary vs supplementary: Focus on contentPaths for localised pages. Set docusaurusCatalogDir when you also need Docusaurus shell JSON from write-translations. Omit docusaurusCatalogDir if you only translate pages.
Step 2: Translate documents
ai-i18n-tools translate-docsThis translates all files in every docs[] block's contentPaths (and Docusaurus catalog JSON when docusaurusCatalogDir is set) to all effective documentation locales. Already-translated segments are served from the SQLite cache - only new or changed segments are sent to the LLM.
To translate a single locale:
ai-i18n-tools translate-docs --locale deTo check what needs translating:
ai-i18n-tools statusFor flags, cache behaviour, and batch prompt format, see CLI options.
Complex Markdown and failed quality checks
translate-docs checks that each translated segment preserves markdown structure (including emphasis parsed from the document). Paragraphs that stack many bold spans around `inline code`, nest backticks inside bold (for example template literals such as `fetch(\`/locales/${code}.json\`)`), or weave bold and code through one long sentence are fragile: some locales need different word order, which can change how ** and ` line up after translation and trigger CLI errors such as AST mismatch.
If you hit that kind of validation failure, prefer simplifying the source-language text - split the paragraph, move an example into a fenced code block, or describe the same idea with fewer layered bold/code pairs - rather than expecting every model and locale to reproduce dense inline markup perfectly.
When every configured model fails with an AST mismatch on the same segment, translate-docs can automatically split that segment into smaller parts (list midpoint first, then single list items or shorter paragraph chunks), retry each part from the first model, and rejoin the result under the original segment cache key. This is on by default (segmentSplitting.qualityRetrySplit); set it to false to stop after model exhaustion. The run summary reports Quality split retries when this fallback runs.
To see which segments failed, how often, and the stored quality / error messages, use the Translation Dashboard's Failures tab (Translation Dashboard → Failures).