zudo-paper

Docusaurusのi18nの仕組み

Author: Takazudo | 作成: 2026/03/05

概要

Docusaurusサイトで日英の多言語対応を行った。その過程でDocusaurusのi18nの仕組みを一通り理解する必要があったので、設定からファイル構造、ビルド、開発サーバーまでの全体像をまとめた開発メモ。

i18n設定

docusaurus.config.tsに以下のような設定を追加する。

i18n: {
  defaultLocale: 'en',
  locales: ['en', 'ja'],
  localeConfigs: {
    en: { label: 'English' },
    ja: { label: '日本語' },
  },
},

defaultLocaleがルートURL(/)で配信されるロケール。非デフォルトロケールはURLにプレフィックスが付く。英語がデフォルトなら日本語は/ja/docs/...のようなパスになる。

localeConfigslabelはロケール切り替えドロップダウンの表示名。

ロケール切り替えドロップダウンの表示

ロケール切り替えUI

navbarの設定にビルトインのlocaleDropdownアイテムを追加する。

{
  type: 'localeDropdown',
  position: 'right',
},

これで現在のページの他ロケール版へのリンクが自動生成される。例えば/docs/guides/を見ているときにドロップダウンから日本語を選ぶと/ja/docs/guides/に遷移する。

ファイル構造のミラーリング

Docusaurusのi18nは「ディレクトリ構造のミラーリング」が基本。英語のdocs配下の構造をそのままi18nディレクトリに再現する。

英語(元):
docs/guides/getting-started.mdx
 
日本語(翻訳):
i18n/ja/docusaurus-plugin-content-docs/current/guides/getting-started.mdx

パスの対応関係はこうなる。

  • docs/i18n/ja/docusaurus-plugin-content-docs/current/
  • currentはDocusaurusのバージョニング機能のデフォルトバージョンを指す
  • ファイル名は完全に同一でなければならない
  • ディレクトリ構造も完全に同一でなければならない

元のdocsディレクトリがこういう構造だとする。

docs/
├── overview/
│   ├── _category_.json
│   ├── index.mdx
│   ├── setup.mdx
│   └── configuration.mdx
├── guides/
│   ├── index.mdx
│   ├── getting-started.mdx
│   ├── advanced-usage.mdx
│   └── ...
├── api/
├── tutorials/
└── faq/

この構造をそのままミラーリングしたi18nディレクトリ全体のツリーはこうなる。

i18n/ja/
├── code.json
├── docusaurus-plugin-content-docs/
│   ├── current.json
│   └── current/
│       ├── overview/
│       │   ├── _category_.json
│       │   ├── index.mdx
│       │   ├── setup.mdx
│       │   └── configuration.mdx
│       ├── guides/
│       │   ├── index.mdx
│       │   ├── getting-started.mdx
│       │   ├── advanced-usage.mdx
│       │   └── ...
│       ├── api/
│       ├── tutorials/
│       └── faq/
└── docusaurus-theme-classic/
    ├── navbar.json
    └── footer.json

code.jsonがテーマUI文字列、docusaurus-plugin-content-docs/配下がドキュメント本文とサイドバーカテゴリ、docusaurus-theme-classic/配下がナビバー・フッター。翻訳の4レイヤーがそのままディレクトリ構造に反映されている。

翻訳対象の4つのレイヤー

Docusaurusの翻訳は4つのレイヤーに分かれる。

ドキュメント本文(MDXファイル)

i18n/ja/docusaurus-plugin-content-docs/current/配下に、英語のdocsディレクトリをそのままミラーリングする。

  • frontmatter(sidebar_position等)はそのまま、本文のみ翻訳
  • import文やカスタムコンポーネントの呼び出しはそのまま
  • コードブロックはそのまま、コメントのみ翻訳

実際のファイルペアを見るとわかりやすい。guides/index.mdxの例。

英語(docs/guides/index.mdx):

---
sidebar_position: 0
---
 
# Guides
 
Step-by-step guides for common tasks. Each guide walks you through a specific workflow from start to finish.
 
- [Getting Started](./getting-started.mdx) — Initial setup and first steps
- [Advanced Usage](./advanced-usage.mdx) — Tips for power users

日本語(i18n/ja/docusaurus-plugin-content-docs/current/guides/index.mdx):

---
sidebar_position: 0
---
 
# ガイド
 
よくあるタスクのステップバイステップガイド。各ガイドでは、特定のワークフローを最初から最後まで説明する。
 
- [はじめに](./getting-started.mdx) — 初期セットアップと最初のステップ
- [高度な使い方](./advanced-usage.mdx) — パワーユーザー向けのヒント

frontmatter(sidebar_position: 0)は英語と同一。H1見出しとリンクテキストは翻訳する。リンクのパス(ファイル名)はそのまま。この「パスは同一、テキストだけ翻訳」というのがDocusaurusのi18nの基本パターンになる。

テーマUI文字列(code.json)

i18n/ja/code.jsonで、Docusaurusのテーマが使うUI文字列を翻訳する。

  • 「前へ」「次へ」「コピー」「コピーしました」「先頭へ戻る」等
  • admonitionのタイトル(「注記」「ヒント」「警告」等)
  • パンくずリスト、検索UI、エラーページ等

docusaurus write-translationsコマンドでテンプレートを生成できる。まずこれで雛形を出力してから翻訳していく流れになる。

実際のi18n/ja/code.jsonの抜粋はこうなる。

{
  "theme.ErrorPageContent.title": {
    "message": "エラーが発生しました",
    "description": "The title of the fallback page when the page crashed"
  },
  "theme.BackToTopButton.buttonAriaLabel": {
    "message": "先頭へ戻る",
    "description": "The ARIA label for the back to top button"
  },
  "theme.docs.paginator.previous": {
    "message": "前へ",
    "description": "The label used to navigate to the previous doc"
  },
  "theme.docs.paginator.next": {
    "message": "次へ",
    "description": "The label used to navigate to the next doc"
  },
  "theme.CodeBlock.copy": {
    "message": "コピー",
    "description": "The copy button label on code blocks"
  },
  "theme.CodeBlock.copied": {
    "message": "コピーしました",
    "description": "The copied button label on code blocks"
  },
  "theme.admonition.note": {
    "message": "注記",
    "description": "The default label used for the Note admonition (:::note)"
  }
}

キーはDocusaurusのテーマコンポーネントの内部IDで、messageが翻訳後の文字列、descriptionが翻訳者向けのコンテキスト。descriptionは英語のまま残しておいて問題ない。ページネーター、コードブロックのコピーボタン、admonitionのラベルなど、サイト全体のUIに散らばっている文字列がここに集約されている。

ナビバー・フッター(navbar.json, footer.json)

以下の場所に配置する。

  • i18n/ja/docusaurus-theme-classic/navbar.json
  • i18n/ja/docusaurus-theme-classic/footer.json

サイトタイトル、ナビバーリンクのラベル等を翻訳する。

{
  "title": {
    "message": "マイプロジェクト",
    "description": "The title in the navbar"
  },
  "item.label.Guides": {
    "message": "ガイド",
    "description": "Navbar item with label Guides"
  }
}

各エントリにmessage(翻訳後のテキスト)とdescription(翻訳者向けのコンテキスト説明)がある。

footer.jsonも同じ形式で配置する。

{
  "copyright": {
    "message": "My Project. Built with Docusaurus.",
    "description": "The footer copyright"
  }
}

このプロジェクトではフッターのcopyrightは意図的に英語のまま残した。翻訳ファイルは置くがmessageを英語にしておけば、日本語ロケールでも英語表示になる。翻訳対象のファイルが存在しないのと、ファイルは存在するが中身が英語なのとでは意味が違う。ファイルがないとDocusaurusがフォールバック挙動をするので、明示的に英語を指定しておく方が安全。

サイドバーカテゴリ

サイドバーのカテゴリラベルは2つの方法で翻訳できる。

1つ目はi18n/ja/docusaurus-plugin-content-docs/current.jsonに翻訳を定義する方法。

{
  "sidebar.tutorialsSidebar.category.Advanced Topics": {
    "message": "応用トピック"
  }
}

2つ目は_category_.jsonをi18nディレクトリに配置する方法。両方ある場合は_category_.jsonが優先される。

_category_.jsonのペアはこうなる。

英語(docs/guides/_category_.json):

{
  "label": "Guides",
  "position": 1
}

日本語(i18n/ja/docusaurus-plugin-content-docs/current/guides/_category_.json):

{
  "label": "ガイド",
  "position": 1
}

labelだけ翻訳してpositionはそのまま。ファイル名(_category_.json)もディレクトリ名(guides/)も英語版と同一。翻訳されるのはサイドバーに表示されるカテゴリ名だけということになる。

ビルドの仕組み

docusaurus buildを実行すると、各ロケールごとに完全に独立したサイトをビルドする。

出力先は以下の通り。

  • build/ — 英語
  • build/ja/ — 日本語

それぞれ独自のindex.htmlsitemap.xml404.htmlを持つ。静的アセット(画像等)は共有される。

ビルドログはこうなる。

[INFO] Website will be built for all these locales:
- en
- ja
[INFO] [en] Creating an optimized production build...
[SUCCESS] Generated static files in "build".
[INFO] [ja] Creating an optimized production build...
[SUCCESS] Generated static files in "build/ja".

開発サーバーの注意点

ここは注意が必要なところ。

docusaurus startデフォルトロケールのみ配信する。/ja/にアクセスしても404になる。日本語で開発するにはdocusaurus start --locale jaが必要。同時に両方のロケールを開発サーバーで動かすことはできない。

実際に起きることとしては、ロケールドロップダウンは開発サーバーでも表示される。クリックすると/ja/...に遷移するが、そのパスは存在しないので404になる。これはDocusaurusの仕様であり、バグではない。

ビルド後のdocusaurus serve(またはnpx serve build)なら両方のロケールを確認できる。

package.jsonに別コマンドを登録しておくと便利。

{
  "start": "docusaurus start",
  "start:ja": "docusaurus start --locale ja"
}

翻訳漏れが起きたときの症状

翻訳ファイルが存在しないページでロケールを切り替えると404になる。

実際に起きたケースとしては、英語のguides/セクション(3ファイル)を追加した後、日本語翻訳を作り忘れた。英語ページからロケールドロップダウンで日本語に切り替えると/ja/docs/guides/が404になった。解決策はi18n/ja/docusaurus-plugin-content-docs/current/guides/に翻訳ファイルを追加すること。

ビルド自体はエラーにならない。翻訳がないページは単にスキップされるので、気づきにくい。

まとめ

Docusaurusのi18nは「ディレクトリミラーリング + JSON翻訳ファイル」というアーキテクチャ。

  1. ファイル構造を完全にミラーリングすること
  2. 翻訳は4レイヤー(ドキュメント本文、テーマUI、ナビバー/フッター、サイドバーカテゴリ)
  3. 開発サーバーは1ロケールずつしか動かせない
  4. 翻訳漏れはビルドエラーにならないので注意