How to Set Up Internationalization (i18n) for Docusaurus Sites

Configure the i18n object in docusaurus.config.js, run npx docusaurus write-translations to generate Chrome i18n JSON files, and place translated content under i18n/<locale>/ to serve multilingual static sites.

The facebook/docusaurus static site generator provides a file-system-driven i18n architecture that enables publishing documentation and blogs in multiple locales from a single codebase. Setting up Docusaurus internationalization requires declarative configuration, CLI scaffolding, and organized locale folders that the build pipeline merges at runtime.

Configure the i18n Object in docusaurus.config.js

Every Docusaurus i18n setup begins with the i18n configuration block in your root config file. According to the API documentation in website/docs/api/docusaurus.config.js.mdx, you must declare a defaultLocale, a complete list of locales, and optional localeConfigs for per-locale customization.

// docusaurus.config.js
module.exports = {
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'fr', 'es'],
    localeConfigs: {
      en: {
        label: 'English',
        direction: 'ltr',
        htmlLang: 'en-US',
        path: 'en',
      },
      fr: {
        label: 'Français',
        direction: 'ltr',
        htmlLang: 'fr-FR',
        path: 'fr',
        url: 'https://fr.example.com',
      },
      es: {
        label: 'Español',
        direction: 'ltr',
        path: 'es',
      },
    },
  },
};

The localeConfigs object supports fine-grained control over URL routing, HTML language attributes, and text direction. Setting a custom url for specific locales enables multi-domain deployments while Docusaurus automatically generates the correct hreflang SEO tags.

Scaffold Translation Files with the CLI

Docusaurus provides the write-translations CLI command to generate the initial JSON scaffolding for each locale. This command reads your i18n configuration and creates the necessary folder structure under website/i18n/<locale>/.


# Generate translation files for all configured locales

npx docusaurus write-translations

# Generate for a specific locale only

npx docusaurus write-translations --locale fr

The CLI creates code.json for React component translations and plugin-specific JSON files such as docusaurus-theme-classic/navbar.json and docusaurus-plugin-content-docs/plugin-options.json. These files follow the Chrome i18n format expected by the Docusaurus runtime.

Understanding the Chrome i18n JSON Format

All translation files in Docusaurus use the standard Chrome i18n JSON structure documented in website/docs/i18n/i18n-introduction.mdx. Each key maps to an object containing a message (the translatable string) and a description (context for translators).

{
  "theme.navbar.toggleDarkMode": {
    "message": "Toggle dark mode",
    "description": "Navbar button tooltip for dark mode"
  },
  "theme.footer.followUs": {
    "message": "Follow us",
    "description": "Footer section title"
  }
}

Replace only the message values with your translations. The description field remains in English to guide translation platforms like Crowdin, Transifex, or Phrase, all of which natively support this JSON schema.

Organize Locale-Specific Content

Translated markdown and MDX files follow a parallel folder structure under i18n/<locale>/docusaurus-plugin-content-docs/current/ (or /version-1.0/ for versioned docs). As described in website/docs/i18n/i18n-introduction.mdx, you must manually copy source content into these directories and translate the body text.


# Create French locale directory structure

mkdir -p website/i18n/fr/docusaurus-plugin-content-docs/current

# Copy original documentation for translation

cp -r website/docs/. website/i18n/fr/docusaurus-plugin-content-docs/current/

Edit the files in the locale folder to provide French content while preserving the original filenames. Docusaurus automatically serves the correct file based on the URL locale prefix or the user's locale switcher selection.

Runtime Build and Deployment

During the build process, Docusaurus utilizes utility functions from packages/docusaurus-utils/src/i18nUtils.ts to resolve and merge translations. The getPluginI18nPath function (lines 49-66) constructs absolute paths to translation directories, while mergeTranslations (lines 22-26) aggregates JSON files from all plugins into a single translation map for the current locale.

The getLocaleConfig function (lines 72-80) returns runtime configuration including label, direction, and URL overrides. This enables the server to generate locale-prefixed routes and inject the correct <html lang="..."> attributes.

For multi-domain setups, configure distinct url values in localeConfigs. The build pipeline generates separate static assets for each locale with proper canonical links and alternate language metadata.

Add a Locale Dropdown to Your Navbar

Enable user locale switching by adding the localeDropdown item type to your theme configuration:

// docusaurus.config.js
themeConfig: {
  navbar: {
    items: [
      {
        type: 'localeDropdown',
        position: 'right',
      },
    ],
  },
}

Docusaurus automatically populates this dropdown with the labels defined in your i18n.localeConfigs and handles routing between language versions.

Summary

  • Declare i18n settings in docusaurus.config.js with defaultLocale, locales, and optional localeConfigs for per-locale URLs and HTML attributes.
  • Generate translation scaffolding using npx docusaurus write-translations, which creates Chrome i18n JSON files under website/i18n/<locale>/.
  • Translate JSON files by updating message values while preserving the description fields for context.
  • Place translated MDX files in parallel paths under i18n/<locale>/docusaurus-plugin-content-docs/current/ to serve localized content.
  • Leverage utility functions like getPluginI18nPath and mergeTranslations from packages/docusaurus-utils/src/i18nUtils.ts to understand how the build pipeline resolves translations.
  • Configure multi-domain deployments by setting unique url values per locale in your configuration.

Frequently Asked Questions

How do I add a new language to an existing Docusaurus site?

Add the locale code to the locales array in docusaurus.config.js, then run npx docusaurus write-translations --locale <new-locale>. This creates the necessary folder structure and JSON files under i18n/<new-locale>/. Copy your markdown files into the appropriate plugin subdirectory and translate the content.

What translation format does Docusaurus use?

Docusaurus uses the Chrome i18n JSON format, a structured JSON file where each translation key maps to an object with message (the text) and description (translator context) properties. This format is compatible with major translation management platforms including Crowdin and Transifex.

Can I host different languages on separate domains?

Yes. Configure the url property inside localeConfigs for specific locales. For example, set fr: { url: 'https://fr.example.com' } to host the French version on its own domain. Docusaurus generates the appropriate hreflang tags and handles base URL resolution during the build process.

Where does Docusaurus store translation files?

Translation files reside in the i18n/<locale>/ directory at your project root. Each plugin or theme stores its translations in subdirectories named after the plugin (e.g., docusaurus-plugin-content-docs, docusaurus-theme-classic). The utility function getPluginI18nPath in packages/docusaurus-utils/src/i18nUtils.ts calculates these paths at build time.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →