Internationalisation (i18n)
Publier un site en plusieurs langues — URL préfixées par langue, navigation par langue, chaînes d’interface traduites et hreflang automatique.
Un site juicer peut livrer le même contenu en plusieurs langues. Chaque langue
obtient sa propre arborescence de contenu, son propre espace d’URL et sa propre
navigation ; les pages qui existent en plus d’une langue s’interrelient
automatiquement, et l’habillage d’interface (libellés de boutons,
« Précédent »/« Suivant », champ de recherche, …) est traduit via des
dictionnaires. Les sites monolingues ne paient rien pour tout cela — rien ne
s’active tant que vous ne déclarez pas une liste languages.
Cette page documente chaque rouage. La documentation de juicer.build que vous lisez est elle-même bilingue (anglais + français), donc tout est éprouvé sur soi.
L’activer
Déclarez les langues et la langue par défaut dans site.toml :
languages = ["en", "fr"]
defaultLanguage = "en"
defaultLanguageInRoot = true
languages— la liste des codes de langue que vous publiez. Une liste vide ou absente signifie un site monolingue (aucun changement de comportement).defaultLanguage— la langue de repli. Une traduction manquante (d’une page ou d’une chaîne d’interface) retombe sur cette langue. Par défaut, la première entrée delanguages; sur un site sanslanguages, c’est"en".defaultLanguageInRoot— quandtrue, la langue par défaut est servie à la racine du site sans préfixe/<code>/, et seules les autres langues obtiennent un préfixe. Quandfalse(le défaut), chaque langue est préfixée, y compris la langue par défaut.
Disposition du contenu
Une fois languages défini, le contenu réside un répertoire plus bas — sous
content/<lang>/ :
content/
├── en/
│ ├── _index.md
│ └── getting-started/
│ ├── _index.md
│ └── installation.md
└── fr/
├── _index.md
└── getting-started/
├── _index.md
└── installation.md
La langue d’une page est le premier segment de chemin sous content/. Deux pages
qui partagent le même chemin après le segment de langue — en/getting-started/installation.md
et fr/getting-started/installation.md — sont des traductions l’une de l’autre.
Vous n’avez pas à tout traduire : une page qui n’existe que dans une langue n’a
simplement aucune traduction, et rien ne pointe vers une page manquante.
URL
defaultLanguageInRoot décide de la forme de l’espace d’URL. Avec la
configuration ci-dessus (en par défaut, à la racine) :
| Page | URL |
|---|---|
content/en/getting-started/installation.md | /getting-started/installation/ |
content/fr/getting-started/installation.md | /fr/getting-started/installation/ |
La langue par défaut conserve les URL propres, sans préfixe — important quand vous
ajoutez une seconde langue à un site existant et ne voulez pas casser les liens
entrants. Mettez defaultLanguageInRoot = false pour préfixer chaque langue
symétriquement (/en/… et /fr/…).
Construire des liens préfixés par langue à la main est source d’erreurs. Utilisez
les assistants relLangURL / absLangURL — ils
appliquent le bon préfixe pour vous.
Données de langue par page
Chaque page expose sa langue et ses traductions dans le contexte de rendu :
.page.lang— le code de langue de la page (""sur un site monolingue)..page.translations— la liste des versions dans les autres langues de cette page. Chaque entrée portelang,titleeturl. Vide quand la page n’a pas de traduction..page.languages— toutes les langues configurées (dans l’ordre déclaré), chacune aveclang, uneurlvers laquelle basculer et un indicateurcurrent. L’urlest l’URL propre de la page pour la langue courante, sa traduction là où il en existe une, et l’accueil de cette langue sinon — l’entrée n’est donc jamais manquante, même sur une page non traduite. Vide pour les sites monolingues.
.page.languages est ce qu’un sélecteur de langue complet itère — il offre
toujours chaque langue, à la manière de Starlight ou Docusaurus :
{{ if .page.languages }}
<details aria-label="{{ i18n .page.lang 'aria_language' }}">
<summary>{{ i18n .page.lang 'langname' }}</summary>
{{ for l <- .page.languages }}
<a href="{{ l.url }}" hreflang="{{ l.lang }}"{{ if l.current }} aria-current="true"{{ end }}>
{{ i18n l.lang 'langname' }}
</a>
{{ end }}
</details>
{{ end }}
Le thème juicerdocs livre ceci sous forme de menu déroulant dans sa barre
supérieure. (Utilisez plutôt .page.translations quand vous voulez un sélecteur
qui ne liste que les traductions existantes — pratique pour une bascule en
ligne à deux langues.)
Chaînes d’interface : l’assistant i18n
Le texte d’habillage — libellés de boutons, flèches de pagination, champ de recherche — est recherché par clé plutôt que codé en dur, pour pouvoir être traduit :
{{ i18n .page.lang 'nav_prev' }}
i18n prend un code de langue et une clé. La recherche retombe dans cet
ordre :
- le dictionnaire de la langue demandée,
- le dictionnaire de la
defaultLanguage, - la clé littérale (pour qu’une chaîne manquante soit visible, pas vide).
Comme la langue est le premier argument, {{ i18n t.lang 'langname' }} recherche
une clé dans le tableau d’une autre langue — c’est ainsi que le sélecteur
ci-dessus affiche le nom propre de chaque langue.
Dictionnaires
Les chaînes proviennent de fichiers i18n/<lang>.toml — des tableaux plats
clé = "valeur" :
# i18n/fr.toml# i18n/fr.toml
nav_prev = "Précédent"
nav_next = "Suivant"
Les dictionnaires sont recueillis à deux endroits et fusionnés :
- le(s) thème(s) actif(s) —
<theme>/i18n/<lang>.toml - votre site —
<src>/i18n/<lang>.toml
avec la même priorité que toute autre ressource superposée par thème : votre site l’emporte sur un thème, et un thème plus tôt dans la chaîne de recherche l’emporte sur un thème plus tardif (hérité). La fusion est par langue et par clé, de sorte qu’un thème peut livrer un dictionnaire d’interface anglais complet pendant que votre site n’ajoute que la poignée de clés qu’il supplante — ou les langues supplémentaires qu’il publie.
C’est pourquoi un thème comme juicerdocs rend un habillage anglais sans aucune
configuration : il livre son propre i18n/en.toml. Pour traduire l’habillage,
déposez un i18n/fr.toml dans votre site (ou supplantez des clés individuelles) ;
vous n’avez jamais à forker le thème.
Navigation consciente de la langue
La barre latérale parcourt .site.root.subsections. Sur un site multilingue,
.site.root est délimité à la langue de la page courante — il se résout vers
le <lang>/_index.md de cette langue. Ainsi une page française obtient l’arbre de
sections français, une page anglaise l’anglais, sans aucun travail par thème. Une
section qui n’a pas encore été traduite n’apparaît simplement pas dans la
navigation de cette langue.
.page.prev / .page.next — la pagination séquentielle — sont délimités de la
même façon : la navigation ne parcourt que l’ordre de lecture de la langue
courante, de sorte que la dernière page anglaise ne pointe jamais « suivant » vers
le français.
URLs conscientes de la langue
relLangURL et absLangURL sont les compagnons conscients de la langue de
relURL / absURL. Ils prennent la langue comme premier argument et préfixent
le chemin du segment d’URL de cette langue :
<a href="{{ relLangURL .page.lang '/getting-started/' }}">…</a>
Sur une page anglaise (par défaut, à la racine) cela donne /getting-started/ ;
sur une page française, /fr/getting-started/. Utilisez-les pour les liens fixes
dans les gabarits partagés — comme un appel à l’action de héros — afin qu’ils
restent dans la langue du lecteur. (.page.url et .page.translations[].url sont
déjà corrects pour la langue ; vous n’avez besoin de relLangURL que pour les
chemins que vous écrivez à la main.)
Sitemap et hreflang
Quand un site est multilingue, sitemap.xml gagne automatiquement des entrées
<xhtml:link rel="alternate" hreflang="…"> reliant chaque page à ses traductions,
pour que les moteurs de recherche servent la bonne langue. Les sites monolingues
obtiennent un sitemap ordinaire, sans bruit hreflang. Aucune configuration requise
dans un cas comme dans l’autre.
Ce qui reste sans configuration
Tout ce qui figure sur cette page est dormant tant que languages n’est pas
défini. Un site sans liste languages se construit à l’octet près comme avant
l’existence de l’i18n : .page.lang vaut "", .page.translations est vide, le
sitemap n’a pas de hreflang, le contenu reste dans content/ (pas
content/<lang>/), et l’assistant i18n résout toujours les dictionnaires de
thème via le repli sur la langue par défaut, de sorte que l’habillage thémé se rend
en anglais.