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 i18n du site pour déclarer les locales i18n :
module.exports = {
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
Ajouter un élément à la barre de navigation de type localeDropdown
afin que l'utilisateur puisse sélectionner la locale de son choix :
module.exports = {
themeConfig: {
navbar: {
items: [
{
type: 'localeDropdown',
position: 'left',
},
],
},
},
};
Démarrez votre site
Démarrez votre site localisé en mode développement, en utilisant la locale de votre choix :
- npm
- Yarn
- pnpm
npm run start -- --locale fr
yarn run start --locale fr
pnpm 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.
Démarrez votre site localisé en mode développement, en utilisant la locale de votre choix :
Votre site est accessible à l'adresse http://localhost:3000/fr/.
Docusaurus fournit des traductions par défaut pour les libellés de thème génériques, telles que « Suivant » et « Précédent » pour la pagination.
Traduisez votre site
Toutes les données de traduction pour la locale française sont stockées dans website/i18n/fr
. Chaque plugin fournit son propre contenu traduit dans le dossier correspondant, tandis que le fichier code.json
définit tous les libellés utilisés dans le code React.
Après avoir copié des fichiers, redémarrez votre site avec npm run start -- --locale fr
. Le rechargement à chaud fonctionnera mieux lors de l'édition des fichiers existants.
Traduire votre code React
Pour tout code React que vous avez écrit vous-même : pages React, composants React, etc, vous utiliserez les API de traduction.
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 :
- Le composant
<Translate>
enveloppe une chaîne de caractères en tant qu'élément JSX; - La fonction de rappel
translate()
prend un message et retourne une chaîne de caractères.
Après avoir copié des fichiers, redémarrez votre site avec npm run start -- --locale fr
. Le rechargement à chaud fonctionnera mieux lors de l'édition des fichiers existants.
Un élément JSX est un objet, pas une chaîne. L'utiliser dans des contextes attendant des chaînes de caractères (comme les enfants de <option>
) le contraindra à une chaîne, qui renvoie "[object Object]"
. Bien que nous vous encouragions à utiliser <Translate>
comme enfants JSX, n'utilisez le formulaire de l'élément que lorsqu'il fonctionne réellement.
- Before
- After
import React from 'react';
import Layout from '@theme/Layout';
import Link from '@docusaurus/Link';
export default function Home() {
return (
<Layout>
<h1>Bienvenue sur mon site web</h1>
<main>
Vous pouvez aussi visiter mon
<Link to="https://docusaurus.io/blog">blog</Link>
<img
src="/img/home.png"
alt="Home icon"
/>
</main>
</Layout>
);
}
import React from 'react';
import Layout from '@theme/Layout';
import Link from '@docusaurus/Link';
import Translate, {translate} from '@docusaurus/Translate';
export default function Home() {
return (
<Layout>
<h1>
<Translate>Welcome to my website</Translate>
</h1>
<main>
<Translate
id="homepage.visitMyBlog"
description="The homepage message to ask the user to visit my blog"
values={{
blogLink: (
<Link to="https://docusaurus.io/blog">
<Translate
id="homepage.visitMyBlog.linkLabel"
description="The label for the link to my blog">
blog
</Translate>
</Link>
),
}}>
{'You can also visit my {blogLink}'}
</Translate>
<img
src="/img/home.png"
alt={
translate({
message: 'Home icon',
description: 'The homepage icon alt message',
})
}
/>
</main>
</Layout>
);
}
Docusaurus fournit un runtime de traduction très petit et léger et ne prend en charge que l'interpolation de placeholders, en utilisant un sous-ensemble du Format de message ICU.
Un élément JSX est un objet, pas une chaîne. L'utiliser dans des contextes attendant des chaînes de caractères (comme les enfants de <option>
) le contraindra à une chaîne, qui renvoie "[object Object]"
.
La commande docusaurus write-translations
analysera statiquement tous les fichiers de code React utilisés dans votre site, extraira les appels à ces APIs, et les agrégera dans le fichier code.json
. 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é). Dans vos appels aux API de traduction (<Translate>
ou translate()
), vous devez spécifier soit le message non traduit par défaut, soit l'ID, afin que Docusaurus puisse correctement corréler chaque entrée de traduction à l'appel de l'API.
La plupart des sites web de documentation sont généralement statiques et n'ont pas besoin de fonctionnalités i18n avancées (nombre, genre, etc.). Utilisez une bibliothèque comme react-intl pour des cas d'utilisation plus avancés. Par conséquent, les messages dynamiques ne peuvent pas être extraits, car le message est une expression, pas une chaîne :
const items = [
{id: 1, title: 'Hello'},
{id: 2, title: 'World'},
];
function ItemsList() {
return (
<ul>
{/* NE LE FAITES PAS : ne fonctionne pas avec la commande write-translations */}
{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>
{/* Les titres sont maintenant déjà traduits lors du rendu ! */}
{items.map((item) => (
<li key={item.id}>{item.title}</li>
))}
<ul>
);
}
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 ».
Pluralisation
Lorsque vous exécutez write-translations
, vous remarquerez que certains libellés sont pluralisés :
{
// ...
"theme.blog.post.plurals": "One post|{count} posts"
// ...
}
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 :
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` fournira le sélecteur pluriel pour la locale actuelle
const {selectMessage} = usePluralForm();
// Sélectionne le libellé pluralisé approprié en fonction de `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 utiliseIntl.PluralRules
pour résoudre et sélectionner les formes plurielles. Il est important de fournir le bon nombre de formes plurielles dans le bon ordre pour que selectMessage
fonctionne.
Traduire les données du plugin
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
- Les libellés des catégories de la barre latérale dans
sidebars.js
- Titre de la barre latérale du blog dans les options du plugin
- ...
Exécutez la commande write-translations :
- npm
- Yarn
- pnpm
npm run write-translations -- --locale fr
yarn write-translations --locale fr
pnpm run write-translations -- --locale fr
Docusaurus utilise Intl.PluralRules
pour résoudre et sélectionner les formes plurielles. Il est important de fournir le bon nombre de formes plurielles dans le bon ordre pour que selectMessage
fonctionne.
{
// Aucun ID pour le composant <Translate> : le message par défaut est utilisé comme 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:
{
"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"
}
}
Les fichiers de traduction JSON sont utilisés pour tout ce qui est disséminé dans votre code :
Traduisez les fichiers Markdown
Exécutez la commande write-translations :
Traduisez les docs
Copiez vos fichiers docs Markdown depuis docs/
vers i18n/fr/docusaurus-plugin-content-docs/current
, et traduisez-les :
mkdir -p i18n/fr/docusaurus-plugin-content-docs/current
cp -r docs/** i18n/fr/docusaurus-plugin-content-docs/current
Notez que le plugin docusaurus-plugin-content-docs
divise toujours son contenu par versions. Les données dans le dossier ./docs
seront traduites dans le sous-dossier current
et le fichier current.json
. Consultez le guide de version de doc pour plus d'informations sur ce que signifie "current".
Traduisez le blog
Copiez vos fichiers docs Markdown depuis docs/
vers i18n/fr/docusaurus-plugin-content-docs/current
, et traduisez-les :
mkdir -p i18n/fr/docusaurus-plugin-content-blog
cp -r blog/** i18n/fr/docusaurus-plugin-content-blog
Traduisez les pages
Copiez vos pages de fichiers Markdown vers i18n/fr/docusaurus-plugin-content-pages
et traduisez-les :
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
We only copy .md
and .mdx
files, as React pages are translated through JSON translation files already.
Copiez vos pages de fichiers Markdown vers i18n/fr/docusaurus-plugin-content-pages
et traduisez-les :
Par défaut, un titre Markdown ### Hello World
aura un ID généré hello-world
. D'autres documents peuvent le cibler avec [link](#hello-world)
. Cependant, après traduction, le titre devient ### Bonjour le Monde
, avec l'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.
:::
Déployez votre site
Vous pouvez choisir de déployer votre site sous un domaine unique ou utiliser plusieurs (sous-)domaines.
Déploiement sur un domaine unique
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
- Yarn
- pnpm
npm run build
yarn build
pnpm run build
Pour les sites localisés, il est recommandé d'utiliser les ID de titre explicites.
site/build
: pour la langue par défaut, l'anglaissite/build/fr
: pour la langue française
You can now deploy the build
folder to the static hosting solution of your choice.
Exécutez la commande suivante :
Les hébergeurs statiques redirigent généralement /unknown/url
vers /404.html
par convention, affichant toujours une page 404 anglaise.
Le site web Docusaurus v2 utilise cette stratégie :
Ce n'est pas toujours possible, et dépend de votre hôte : GitHub Pages ne peut pas le faire, Netlify peut.
Déploiement multi-domaines
Les hébergeurs statiques redirigent généralement /unknown/url
vers /404.html
par convention, affichant toujours une page 404 anglaise.
- npm
- Yarn
- pnpm
npm run build -- --locale fr
yarn build --locale fr
pnpm run build -- --locale fr
Localisez vos 404 pages en configurant votre hôte pour rediriger /fr/*
vers /fr/404.html
.
Ce n'est pas toujours possible, et dépend de votre hôte : GitHub Pages ne peut pas le faire, Netlify peut.
- créez un déploiement par locale
- configurez la commande build appropriée, en utilisant l'option
--locale
- configurez le (sous-)domaine de votre choix pour chaque déploiement
Vous pouvez également construire votre site pour une seule locale :
Hybride
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 :
- Déployez votre site en tant que
fr.docusaurus.io
- Configurez un CDN pour le servir depuis
docusaurus.io/fr
Gestion des traductions
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.
Nous partagerons deux stratégies communes de collaboration en matière de traduction : en utilisant git et en utilisant Crowdin.