Aller au contenu principal
Version: 3.0.0-rc.1

i18n - Tutoriel

Ce tutoriel vous guidera à travers les principes de base du système i18n de Docusaurus.

Nous ajouterons les traductions françaises à un site web Docusaurus en anglais nouvellement initialisé.

Initialisez un nouveau site avec npx create-docusaurus@latest website classic (comme celui-ci).

Configurez votre site

Modifiez docusaurus.config.js pour ajouter le support i18n pour la langue française.

Configuration du site

Utilisez la configuration du site i18n pour déclarer les locales i18n :

docusaurus.config.js
export default {
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr', 'fa'],
localeConfigs: {
en: {
htmlLang: 'en-GB',
},
// Vous pouvez omettre une locale (par exemple, fr) si vous n'avez pas besoin de modifier les paramètres par défaut.
fa: {
direction: 'rtl',
},
},
},
};

Les noms de locales sont utilisés pour les emplacements des fichiers de traduction, ainsi que pour l'URL de base de vos locales traduites. Lors de la compilation de toutes les locales, seule la locale par défaut aura son nom omis dans l'URL de base.

Docusaurus utilise les noms des locales pour fournir des valeurs par défaut judicieuses : l'attribut <html lang="...">, le libellé de la locale, le format du calendrier, etc. Vous pouvez personnaliser ces valeurs par défaut avec le localeConfigs.

Configuration du thème

Ajoutez un *élément à la barre de navigation de type localeDropdown afin que l'utilisateur puisse sélectionner la locale de son choix :

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

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').

Ceci est utile pour mettre en place une détection automatique de la langue sur votre serveur. Par exemple, vous pouvez utiliser ce paramètre pour stocker dans un cookie la locale préférée de l'utilisateur.

Démarrez votre site

Démarrez votre site localisé en mode développement, en utilisant la locale de votre choix :

npm run start -- --locale fr

Votre site est accessible à l'adresse http://localhost:3000/fr/.

Nous n'avons pas encore fourni de traduction, donc le site est principalement non traduit.

astuce

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

Please help us complete those default translations.

attention

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.

Translate your site

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.

remarque

After copying files around, restart your site with npm run start -- --locale fr. Le rechargement à chaud fonctionnera mieux lors de l'édition des fichiers existants.

Translate your React code

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

Repérez tous les libellés de texte dans votre code React qui seront visibles par vos utilisateurs, et marquez-les avec les API de traduction. Il y a deux types d'API :

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

Après avoir copié des fichiers, redémarrez votre site avec npm run start -- --locale fr. For example, the <Translate> can be used as React children, while for props that expect a string, the callback can be used.

attention

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>
);
}
info

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. Les fichiers de traduction seront stockés sous forme de mappage des ID vers les objets de message de traduction (y compris le libellé traduit et la description du libellé). 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. Utilisez une bibliothèque comme react-intl pour des cas d'utilisation plus avancés. 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>
);
}

Cela se comporte toujours correctement au moment de l'exécution. Cependant, à l'avenir, nous pourrions fournir un mécanisme « sans exécution », permettant aux traductions d'être directement incluses dans le code React à travers les transformations de Babel, au lieu d'appeler les APIs à l'exécution. Par conséquent, pour être à l'épreuve du temps, vous devriez toujours préférer les messages analysables statiquement. Par exemple, nous pouvons refactoriser le code ci-dessus en :

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".

Pluralization

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.

Vous pouvez voir les appels aux API de traduction comme de purs marqueurs qui indiquent à Docusaurus que « voici un libellé à remplacer par un message traduit ».

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>
</>
);
}
remarque

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.

Translate plugin data

Vous pouvez aussi mettre les messages de votre propre code au pluriel :

  • Le code React, y compris les libellés traduits que vous avez marqués ci-dessus
  • Les libellés de la barre de navigation et du pied de page dans la configuration du thème
  • Docs sidebar category labels in sidebars.js
  • Titre de la barre latérale du blog dans les options du plugin
  • ...

Run the write-translations command:

npm run write-translations -- --locale fr

Docusaurus utilise Intl.PluralRules pour résoudre et sélectionner les formes plurielles. 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.

Translate Markdown files

Exécutez la commande write-translations :

Translate the docs

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
info

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.

Translate the blog

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

Translate the pages

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/**.md i18n/fr/docusaurus-plugin-content-pages
cp -r src/pages/**.mdx i18n/fr/docusaurus-plugin-content-pages
attention

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.

Nous ne copions que les fichiers .md et .mdx car les pages React sont déjà traduites par des fichiers de traduction JSON.

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

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

Deploy your site

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

Single-domain deployment

Les ID générés ne sont pas toujours adaptés aux sites localisés, car ils vous obligent à localiser tous les liens d'ancrage :

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.

remarque

Le site web Docusaurus utilise cette stratégie :

astuce

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.

Multi-domain deployment

Les hébergeurs statiques redirigent généralement /unknown/url vers /404.html par convention, affichant toujours une page 404 anglaise.

npm run build -- --locale fr

Docusaurus will not add the /fr/ URL prefix.

On your static hosting provider:

  • créez un déploiement par locale
  • configure the appropriate build command, using the --locale option
  • configurez le (sous-)domaine de votre choix pour chaque déploiement
attention

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

Hybrid

Sur votre hébergeur statique :

Il est également possible de déployer chaque locale en tant que sous-domaine séparé, assembler les sous-domaines dans un seul domaine unifié au niveau CDN :

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

Managing translations

Docusaurus ne se soucie pas de la manière dont vous gérez vos traductions : tout ce dont il a besoin, c'est que tous les fichiers de traduction (JSON, Markdown ou autres fichiers de données) soient disponibles dans le système de fichiers lors de la construction. Toutefois, en tant que créateurs de sites, vous devez tenir compte de la manière dont les traductions sont gérées afin que vos collaborateurs puissent collaborer efficacement.

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