# How to Set Up Internationalization (i18n) for Docusaurus Sites

> Easily set up internationalization i18n for Docusaurus sites. Configure your site for multiple languages and serve multilingual content efficiently.

- Repository: [Meta/docusaurus](https://github.com/facebook/docusaurus)
- Tags: how-to-guide
- Published: 2026-03-04

---

**Configure the `i18n` object in [`docusaurus.config.js`](https://github.com/facebook/docusaurus/blob/main/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.

```javascript
// 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>/`.

```bash

# 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`](https://github.com/facebook/docusaurus/blob/main/code.json) for React component translations and plugin-specific JSON files such as [`docusaurus-theme-classic/navbar.json`](https://github.com/facebook/docusaurus/blob/main/docusaurus-theme-classic/navbar.json) and [`docusaurus-plugin-content-docs/plugin-options.json`](https://github.com/facebook/docusaurus/blob/main/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).

```json
{
  "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.

```bash

# 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`](https://github.com/facebook/docusaurus/blob/main/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:

```javascript
// 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`](https://github.com/facebook/docusaurus/blob/main/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`](https://github.com/facebook/docusaurus/blob/main/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`](https://github.com/facebook/docusaurus/blob/main/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`](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-utils/src/i18nUtils.ts) calculates these paths at build time.