Skip to main content

i18n - チュートリアル

This tutorial will walk you through the basics of the Docusaurus i18n system.

We will add French translations to a newly initialized English Docusaurus website.

Initialize a new site with npx create-docusaurus@latest website classic (like this one).

サイトの設定

Modify docusaurus.config.js to add the i18n support for the French language.

サイト設定

Use the site i18n configuration to declare the i18n locales:

docusaurus.config.js
export default {
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr', 'fa'],
localeConfigs: {
en: {
htmlLang: 'en-GB',
},
// You can omit a locale (e.g. fr) if you don't need to override the defaults
fa: {
direction: 'rtl',
},
},
},
};

ロケール名は、翻訳ファイルの場所と翻訳ロケールのベースURLに使用されます。 すべてのロケールを構築する場合、デフォルトのロケールだけがベースURLで名前が省略されます。

Docusaurus uses the locale names to provide sensible defaults: the <html lang="..."> attribute, locale label, calendar format, etc. You can customize these defaults with the localeConfigs.

Theme configuration

Add a navbar item of type localeDropdown so that users can select the locale they want:

docusaurus.config.js
export default {
themeConfig: {
navbar: {
items: [
{
type: 'localeDropdown',
position: 'left',
},
],
},
},
};
ヒント

You can pass a query parameter that will be appended to the URL when a user changes the locale using the dropdown (e.g. queryString: '?persistLocale=true').

これは、サーバーに自動ロケール検出を実装する場合に便利です。 たとえば、このパラメータを使用して、ユーザーの好みのロケールをクッキーに保存できます。

サイトを動かしましょう

指定したロケールで、ローカライズされたサイトを開発モードで起動します。

npm run start -- --locale fr

Your site is accessible at http://localhost:3000/fr/.

サイトを翻訳していないので、ほとんど未翻訳のままです。

ヒント

Docusaurus provides default translations for generic theme labels, such as "Next" and "Previous" for the pagination.

Please help us complete those default translations.

警告

Each locale is a distinct standalone single-page application: it is not possible to start the Docusaurus sites in all locales at the same time.

サイトを翻訳

All translation data for the French locale is stored in website/i18n/fr. Each plugin sources its own translated content under the corresponding folder, while the code.json file defines all text labels used in the React code.

メモ

After copying files around, restart your site with npm run start -- --locale fr. ホットリロードは、既存のファイルを編集するときにうまく動作します。

React のコードを翻訳

For any React code you've written yourself: React pages, React components, etc., you will use the translation APIs.

Reactのコードの中で、ユーザーに見えるテキストラベルをすべて探し出し、翻訳APIでマークします。 APIには2種類あります。

  • The <Translate> component wraps a string as a JSX element;
  • The translate() callback takes a message and returns a string.

より意味的に文脈に合った方を使ってください。 For example, the <Translate> can be used as React children, while for props that expect a string, the callback can be used.

警告

A JSX element is an object, not a string. Using it in contexts expecting strings (such as the children of <option>) would coerce it to a string, which returns "[object Object]". While we encourage you to use <Translate> as JSX children, only use the element form when it actually works.

src/pages/index.js
import React from 'react';
import Layout from '@theme/Layout';
import Link from '@docusaurus/Link';

export default function Home() {
return (
<Layout>
<h1>Welcome to my website</h1>
<main>
You can also visit my
<Link to="https://docusaurus.io/blog">blog</Link>
<img
src="/img/home.png"
alt="Home icon"
/>
</main>
</Layout>
);
}
情報

Docusaurus provides a very small and lightweight translation runtime on purpose, and only supports basic placeholders interpolation, using a subset of the ICU Message Format.

Most documentation websites are generally static and don't need advanced i18n features (plurals, genders, etc.). Use a library like react-intl for more advanced use-cases.

The docusaurus write-translations command will statically analyze all React code files used in your site, extract calls to these APIs, and aggregate them in the code.json file. 翻訳ファイルは、IDから翻訳メッセージオブジェクト(翻訳ラベルとラベルの説明を含む) までのマップとして保存されます。 In your calls to the translation APIs (<Translate> or translate()), you need to specify either the default untranslated message or the ID, in order for Docusaurus to correctly correlate each translation entry to the API call.

text labels must be static

The docusaurus write-translations command only does static analysis of your code. 実際にサイトを動かすわけではありません。 Therefore, dynamic messages can't be extracted, as the message is an expression, not a string:

const items = [
{id: 1, title: 'Hello'},
{id: 2, title: 'World'},
];

function ItemsList() {
return (
<ul>
{/* DON'T DO THIS: doesn't work with the write-translations command */}
{items.map((item) => (
<li key={item.id}>
<Translate>{item.title}</Translate>
</li>
))}
<ul>
);
}

これは実行時でも正しく動作します。 しかし、将来的には、"no-runtime"メカニズムを提供するかもしれません。 実行時にAPIを呼び出すのではなく、Babelの変換を介してReactコード内で直接インライン化できるようにします。 したがって、将来に備えて、常に静的に分析可能なメッセージにしておく必要があります。 例えば、上記のコードをリファクタリングできます。

const items = [
{id: 1, title: <Translate>Hello</Translate>},
{id: 2, title: <Translate>World</Translate>},
];

function ItemsList() {
return (
<ul>
{/* The titles are now already translated when rendering! */}
{items.map((item) => (
<li key={item.id}>{item.title}</li>
))}
<ul>
);
}

You can see the calls to the translation APIs as purely markers that tell Docusaurus that "here's a text label to be replaced with a translated message".

複数形化

When you run write-translations, you will notice that some labels are pluralized:

i18n/en/code.json
{
// ...
"theme.blog.post.plurals": "One post|{count} posts"
// ...
}

Every language will have a list of possible plural categories. Docusaurus will arrange them in the order of ["zero", "one", "two", "few", "many", "other"]. For example, because English (en) has two plural forms ("one" and "other"), the translation message has two labels separated by a pipe (|). For Polish (pl) which has three plural forms ("one", "few", and "many"), you would provide three labels in that order, joined by pipes.

独自のコードのメッセージを複数形にすることもできます。

import {translate} from '@docusaurus/Translate';
import {usePluralForm} from '@docusaurus/theme-common';

function ItemsList({items}) {
// `usePluralForm` will provide the plural selector for the current locale
const {selectMessage} = usePluralForm();
// Select the appropriate pluralized label based on `items.length`
const message = selectMessage(
items.length,
translate(
{message: 'One item|{count} items'},
{count: items.length},
),
);
return (
<>
<h2>{message}</h2>
<ul>{items.map((item) => <li key={item.id}>{item.title}</li>)}<ul>
</>
);
}
メモ

Docusaurus uses Intl.PluralRules to resolve and select plural forms. It is important to provide the right number of plural forms in the right order for selectMessage to work.

プラグインのデータを翻訳

JSON 翻訳ファイルは、コード内に点在するすべてのものに使用されます。

  • 上でマークした翻訳されたラベルを含むReact コード
  • テーマ設定のナビゲーションバーとフッターラベル
  • Docs sidebar category labels in sidebars.js
  • プラグインオプションのサイドバータイトル
  • ...

Run the write-translations command:

npm run write-translations -- --locale fr

翻訳する必要がある JSON 翻訳ファイルを抽出し、初期化します。 The code.json file at the root includes all translation API calls extracted from the source code, which could either be written by you or provided by the themes, some of which may already be translated by default.

i18n/fr/code.json
{
// No ID for the <Translate> component: the default message is used as ID
"Welcome to my website": {
"message": "Welcome to my website"
},
"home.visitMyBlog": {
"message": "You can also visit my {blog}",
"description": "The homepage message to ask the user to visit my blog"
},
"homepage.visitMyBlog.linkLabel": {
"message": "Blog",
"description": "The label for the link to my blog"
},
"Home icon": {
"message": "Home icon",
"description": "The homepage icon alt message"
}
}

Plugins and themes will also write their own JSON translation files, such as:

i18n/fr/docusaurus-theme-classic/navbar.json
{
"title": {
"message": "My Site",
"description": "The title in the navbar"
},
"item.label.Docs": {
"message": "Docs",
"description": "Navbar item with label Docs"
},
"item.label.Blog": {
"message": "Blog",
"description": "Navbar item with label Blog"
},
"item.label.GitHub": {
"message": "GitHub",
"description": "Navbar item with label GitHub"
}
}

Translate the message attribute in the JSON files of i18n/fr, and your site layout and homepage should now be translated.

Markdown ファイルを翻訳

公式DocusaurusコンテンツプラグインはMarkdown/MDXファイルを幅広く使用し、それらを翻訳できます。

ドキュメントを翻訳

Copy your docs Markdown files from docs/ to i18n/fr/docusaurus-plugin-content-docs/current, and translate them:

mkdir -p i18n/fr/docusaurus-plugin-content-docs/current
cp -r docs/. i18n/fr/docusaurus-plugin-content-docs/current
情報

Notice that the docusaurus-plugin-content-docs plugin always divides its content by versions. The data in ./docs folder will be translated in the current subfolder and current.json file. See the doc versioning guide for more information about what "current" means.

ブログを翻訳

Copy your blog Markdown files to i18n/fr/docusaurus-plugin-content-blog, and translate them:

mkdir -p i18n/fr/docusaurus-plugin-content-blog
cp -r blog/. i18n/fr/docusaurus-plugin-content-blog

ページを翻訳

Copy your pages Markdown files to i18n/fr/docusaurus-plugin-content-pages, and translate them:

mkdir -p i18n/fr/docusaurus-plugin-content-pages
cp -r src/pages/. i18n/fr/docusaurus-plugin-content-pages
警告

We only copy .md and .mdx files, as React pages are translated through JSON translation files already.

Use explicit heading IDs

By default, a Markdown heading ### Hello World will have a generated ID hello-world. Other documents can link it with [link](#hello-world). However, after translation, the heading becomes ### Bonjour le Monde, with ID bonjour-le-monde.

生成された ID は、すべてのアンカーリンクをローカライズする必要があるため、ローカライズされたサイトに適合するとは限りません。

- [link](#hello-world).
+ [link](#bonjour-le-monde)

For localized sites, it is recommended to use explicit heading IDs.

サイトをデプロイする

You can choose to deploy your site under a single domain or use multiple (sub)domains.

About localized baseUrls

Docusaurus will automatically add a /<locale>/ path segment to your site for locales except the default one. This heuristic works well for most sites but can be configured on a per-locale basis depending on your deployment requirements.

Read more on the siteConfig.baseUrl docs.

単一ドメインのデプロイメント

以下のコマンドを実行します:

npm run build

Docusaurus will build one single-page application per locale:

  • website/build: for the default, English language
  • website/build/fr: for the French language

You can now deploy the build folder to the static hosting solution of your choice.

メモ

以下のDocusaurusウェブサイトはこの戦略を使用しています。

ヒント

Static hosting providers generally redirect /unknown/url to /404.html by convention, always showing an English 404 page.

Localize your 404 pages by configuring your host to redirect /fr/* to /fr/404.html.

This is not always possible, and depends on your host: GitHub Pages can't do this, Netlify can.

マルチドメインデプロイメント

単一のロケールでサイトを構築することもできます:

npm run build -- --locale fr

When building a single locale at a time, Docusaurus will not add the /fr/ URL prefix automatically, assuming you want to deploy each locale to a distinct domain.

On your static hosting provider:

  • ロケールごとにデプロイメントを1つ作成する
  • configure the appropriate build command, using the --locale option
  • 各デプロイメントに対して選択したサブドメインを設定する
Configuring URLs for each locale

Use the siteConfig.i18n.localeConfigs[<locale>].url attribute to configure a distinct site URL for each locale:

const config = {
i18n: {
localeConfigs: {
en: {
url: 'https://en.docusaurus.io',
baseUrl: '/',
},
fr: {
url: 'https://fr.docusaurus.io',
baseUrl: '/',
},
},
},
};

This helps search engines like Google know about localized versions of your page thanks to <link rel="alternate" hreflang="<locale>"/> meta tags.

This also permits Docusaurus themes to redirect users to the appropriate URL when they switch locale, usually through the Navbar locale dropdown.

Read more on the siteConfig.url and siteConfig.baseUrl docs.

警告

This strategy is not possible with GitHub Pages, as it is only possible to have a single deployment.

ハイブリッド

一部のロケールではサブパスを使用し、他のロケールではサブドメインを使用することができます。

各ロケールを個別のサブドメインとしてデプロイし、CDN レベルで単一の統合ドメインにサブドメインを組み立てることも可能です。

  • Deploy your site as fr.docusaurus.io
  • Configure a CDN to serve it from docusaurus.io/fr

翻訳の管理

Docusaurus は翻訳の管理方法を気にしません。必要なのは、ビルド中にすべての翻訳ファイル (JSON、Markdown、またはその他のデータ ファイル) がファイルシステムで利用可能であることだけです。 しかし、サイト制作者としては、翻訳者がうまくコラボレーションできるように翻訳の管理方法を検討する必要があります。

We will share two common translation collaboration strategies: using git and using Crowdin.