概要
Docusaurusサイトで日英の多言語対応を行った。その過程でDocusaurusのi18nの仕組みを一通り理解する必要があったので、設定からファイル構造、ビルド、開発サーバーまでの全体像をまとめた開発メモ。
i18n設定
docusaurus.config.tsに以下のような設定を追加する。
i18n: {
defaultLocale: 'en',
locales: ['en', 'ja'],
localeConfigs: {
en: { label: 'English' },
ja: { label: '日本語' },
},
},defaultLocaleがルートURL(/)で配信されるロケール。非デフォルトロケールはURLにプレフィックスが付く。英語がデフォルトなら日本語は/ja/docs/...のようなパスになる。
localeConfigsのlabelはロケール切り替えドロップダウンの表示名。

ロケール切り替え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.jsoncode.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.jsoni18n/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.html、sitemap.xml、404.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翻訳ファイル」というアーキテクチャ。
- ファイル構造を完全にミラーリングすること
- 翻訳は4レイヤー(ドキュメント本文、テーマUI、ナビバー/フッター、サイドバーカテゴリ)
- 開発サーバーは1ロケールずつしか動かせない
- 翻訳漏れはビルドエラーにならないので注意