Skip to content

Nextra integration

Use init -t ui-nextra and docsOutput.style: "nextra" for Nextra 4 documentation sites on Next.js App Router. The preset is an alias for doc-system with an empty localeSubpath and BCP-47 locale folder names preserved (localePathLowercase defaults to false, so folders stay pt-BR, zh-Hans, etc.).

See also Documents, and the runnable examples/nextra-docs demo.

Quick start

bash
ai-i18n-tools init -t ui-nextra [-P <provider>]
# edit ai-i18n-tools.config.json (targetLocales, providers, contentPaths)
pnpm run i18n:sync   # or: ai-i18n-tools sync
pnpm run build       # Next.js build (project-specific script)

Enable features.translateDocs when you translate page content, _meta.ts sidebar labels, and theme dictionary modules in one sync run.

Page layout

Nextra 4 with i18n keeps English source MDX under a locale folder (typically content/en/). Translated copies are written to sibling locale folders:

text
content/en/index.mdx              →  content/pt-BR/index.mdx
content/en/guide/getting-started.mdx  →  content/zh-Hans/guide/getting-started.mdx

Configure one docs[] block:

json
{
  "contentPaths": ["content/en"],
  "outputDir": "content",
  "docsOutput": {
    "style": "nextra",
    "docsRoot": "content/en",
    "rewriteNextraLinks": true
  }
}

Point contentPaths at your English .mdx files and directories. Set docsRoot to the English locale folder inside content/.

Wire Nextra internationalization: set i18n.locales and defaultLocale in next.config, and keep targetLocales in ai-i18n-tools.config.json aligned with those locale codes and the content/{locale}/ folder names.

Theme strings

Nextra theme chrome (editLink, search placeholder, footer, and so on) is not extracted from markdown. Author English strings in a TypeScript dictionary module (for example app/_dictionaries/en.ts) and translate it inside translate-docs:

json
{
  "features": {
    "translateDocs": true
  },
  "docs": [
    {
      "contentPaths": ["content/en"],
      "outputDir": "content",
      "nextraDictionaryPath": "app/_dictionaries/en.ts",
      "docsOutput": {
        "style": "nextra",
        "docsRoot": "content/en"
      }
    }
  ]
}

The tool writes app/_dictionaries/{locale}.ts (default template: {dir}/{locale}.ts). Load the per-locale module in app/_dictionaries/get-dictionary.ts and pass translated strings to <Layout>, <Search>, <Footer>, and related theme components.

Do not use json[] for Nextra theme dictionary strings — that pattern is for unrelated app locale bundles only.

Nextra 3+ uses TypeScript _meta.ts / _meta.tsx files for sidebar structure and titles. When docsOutput.style is "nextra", translate-docs automatically collects _meta.ts, _meta.tsx, and _meta.js under docsRoot, translates string literals in the export default { … } meta map, and writes mirrored files under content/{locale}/**.

Recommended pattern: keep English literals inline in content/en/**/_meta.ts (same as swr-site):

text
content/en/_meta.ts           English sidebar labels (source)
content/pt-BR/_meta.ts        Translated copy (generated by translate-docs)

Optional: override collection with docs[].nextraMetaGlob or restrict translatable property names with docs[].nextraMetaTranslatableKeys (default: title, display, breadcrumb).

Do not hand-author JSON sidecars (i18n/meta.en.json) or thin _meta.ts files that import translated JSON — regenerate locale _meta files with sync / translate-docs when English changes.

Example project

examples/nextra-docs — English sources at content/en/, committed pt-BR and zh-Hans page trees, inline _meta.ts files, and app/_dictionaries/{locale}.ts. Run pnpm run dev on port 3070.

Optional: t() for app/ React (hybrid)

Default: _meta.ts / _meta.tsx object-literal strings are translated inside translate-docs — no t() required.

Optional hybrid: teams may additionally use t() + translate-ui for app/ layout chrome, custom MDX components, or _meta.tsx labels that live only inside JSX component bodies (beyond object-literal extraction in v1). This does not replace translate-meta for meta files unless you explicitly refactor sidebar labels into components.

ContentDefault pipelineOptional alternative
MDX page bodiestranslate-docs
_meta.ts / _meta.tsx object titlestranslate-docsrefactor to t() in JSX (hybrid)
app/ layout, _components/nextraDictionaryPath + dictionary .tst() + translate-ui

Example AI agent prompt (copy into Cursor or another coding agent when migrating layout chrome to t()):

markdown
Add i18n to our Nextra 4 app/ layout using ai-i18n-tools translate-ui (optional hybrid).

Context:
- We already translate MDX pages and _meta.ts via translate-docs (default).
- We want t() in app/[lang]/layout.tsx and app/_components/ for labels not covered by nextraDictionaryPath.
- English-as-key: t("Edit this page on GitHub") in source; strings.json + locales/{locale}.json from extract + translate-ui.
- Do not move _meta.ts sidebar labels into t() unless we explicitly ask — translate-docs handles _meta object literals.

Requirements:
1. Wire getRequestConfig / i18n provider for the app router locale param.
2. Replace hard-coded layout strings with t() calls; keep structure and Nextra theme APIs unchanged.
3. Enable features.translateUIStrings, set ui.sourceRoots to app/ (and mdx-components if needed).
4. Do not duplicate dictionary.ts strings that nextraDictionaryPath already translates — pick one approach per string.

After editing: run extract, translate-ui (or sync), verify en + one target locale in dev.

Nextra serves locale-prefixed routes via Next.js i18n (/guide/getting-started, /pt-BR/guide/getting-started). In-page links should stay locale-neutral (/guide/getting-started) so Next.js can prefix the active locale automatically.

Enable the built-in normalizer so translate-docs fixes links in every translated file automatically:

json
"docsOutput": {
  "style": "nextra",
  "docsRoot": "content/en",
  "rewriteNextraLinks": true
}

rewriteNextraLinks defaults to enabled when style is "nextra".

Author in English sourceAfter normalizer
[Guide](content/en/guide/getting-started.mdx)[Guide](/guide/getting-started)
[Guide](../guide/getting-started.mdx)[Guide](/guide/getting-started)
[Demo](https://github.com/org/repo)unchanged (full URL)

Authoring rules

  • Cross-page doc links: use locale-neutral site routes (/guide/…) in English MDX, or content/en/… / relative .mdx paths and let the normalizer rewrite them during sync.
  • Repo files outside the content tree: use full URLs.
  • Do not hand-edit links in content/<locale>/ — regenerate with sync / translate-docs.

Optional locale proxy

Nextra provides a locale-detection proxy for i18n sites. Export it from proxy.ts in your project root:

ts
export { proxy } from 'nextra/locales'

export const config = {
  matcher: [
    '/((?!api|_next/static|_next/image|favicon.ico|icon.svg|apple-icon.png|manifest|_pagefind).*)',
  ],
}

Site locale codes vs sourceLocale: Nextra and Next.js use short route codes (en, pt-BR, zh-Hans) in next.config, content/{locale}/, and the NEXT_LOCALE cookie. sourceLocale in ai-i18n-tools.config.json can be a BCP-47 tag such as en-GB for translation quality — that tag is not a site route. If the browser cookie or Accept-Language resolves to a tag outside i18n.locales (for example en-GB when only en is configured), Nextra’s stock proxy can redirect in a loop. The examples/nextra-docs demo wraps nextra/locales to reset invalid cookies and paths to the default site locale before delegating.

This does not work with output: 'export' static exports. See Nextra i18n docs.

See also Configuration — docsOutput and Output layouts.

Released under the MIT License.