Internationalisation

Explainer prend en charge plusieurs langues pour les trois applications — docs, blog et website — chacune avec une approche adaptée à ses besoins.

Comportement commun

Quelle que soit l’application, la locale est conservée via un cookie (locale) défini sur le domaine racine. Cela signifie qu’un changement de langue sur un sous-domaine (par ex. blog.example.com) est automatiquement pris en compte par les autres (par ex. docs.example.com).

Ordre de détection (lors de la première visite) :

  1. Cookie locale (défini lorsque l’utilisateur change de langue explicitement)
  2. Langue du navigateur (navigator.language)
  3. Locale par défaut (en)

Docs

L’application docs utilise un routage basé sur la locale dans l’URL. La locale apparaît comme le premier segment de l’URL :

/{locale}/{project}/{path}
URLLocalePage
/en/explainer/getting-startedAnglaisGetting Started
/fr/explainer/getting-startedFrançaisGetting Started

Ajouter une locale

Créer le répertoire de la locale

Dans le répertoire de version de votre projet, créez un nouveau répertoire avec le code de la locale :

mkdir -p apps/docs/src/content/docs/explainer/default/fr

Ajouter le contenu traduit

Créez des fichiers MDX qui reproduisent la structure anglaise :

explainer/default/fr/getting-started.mdx
---
title: Premiers pas
description: Configurez Explainer v2 et commencez à créer votre site de documentation.
order: 1
---

# Premiers pas

Bienvenue dans la documentation d'Explainer v2.

Vérifier

Accédez à /fr/explainer/getting-started. Le sélecteur de langue dans la barre de navigation permet aux utilisateurs de basculer entre les langues disponibles.

Structure des fichiers

explainer/
  default/
    en/                         # Anglais (principal)
      getting-started.mdx
      guides/
        installation.mdx
    fr/                         # Français
      getting-started.mdx
      guides/
        installation.mdx

Comportement de repli

Il n’y a pas de repli automatique vers l’anglais. Chaque locale doit disposer de ses propres fichiers de contenu. Cela garantit que les traductions sont intentionnelles et complètes.

Blog

L’application blog utilise un routage basé sur la locale dans l’URL combiné à un dictionnaire de traductions pour les chaînes d’interface.

Structure des URL

/{locale}                       # Liste des articles
/{locale}/{slug}                # Page d'article
/{locale}/rss.xml               # Flux RSS

Les fichiers de contenu se trouvent dans des répertoires préfixés par la locale sous src/content/posts/ :

src/content/posts/
  en/
    introducing-explainer-v2.mdx
  fr/
    introducing-explainer-v2.mdx

Traductions de l’interface

Toutes les chaînes statiques de l’interface (libellés de navigation, titres, textes de substitution, aria-labels) sont stockées dans un dictionnaire de traductions situé dans src/i18n/ui.ts et accessibles via un helper useTranslations() :

src/i18n/utils.ts
import { ui, defaultLang, type UiKey } from './ui'

export function useTranslations(locale: string) {
  return function t(key: UiKey): string {
    return ui[locale as keyof typeof ui]?.[key] ?? ui[defaultLang][key]
  }
}

Dans les fichiers .astro, la locale provient du paramètre d’URL :

---
const { locale } = Astro.props
const t = useTranslations(locale)
---

<h1>{t('index.heading')}</h1>

Dans les composants .tsx, la locale est passée en tant que prop :

export function TagFilter({ tags, locale = 'en' }: TagFilterProps) {
  const t = useTranslations(locale)
  return <input placeholder={t('tagFilter.placeholder')} />
}

Redirection

La racine / détecte la locale préférée de l’utilisateur (cookie → navigateur → défaut) et redirige vers /{locale}.

Website

Le website est une page d’accueil unique — il n’y a pas de routage basé sur l’URL pour les locales. À la place, il utilise une approche de remplacement des traductions côté client.

Fonctionnement

  1. La page est générée statiquement avec le contenu en anglais par défaut.
  2. Chaque élément traduisible porte un attribut data-t faisant référence à une clé de traduction :
<h1 data-t="hero.title">Explain your ideas</h1>
  1. Un script en ligne détecte la locale (cookie → navigateur → défaut) et remplace le contenu textuel par la traduction correspondante :
document.querySelectorAll('[data-t]').forEach(function (el) {
  const key = el.getAttribute('data-t')
  if (!el.dataset.tDefault) el.dataset.tDefault = el.textContent
  if (translations[key]) el.textContent = translations[key]
})

Dictionnaire de traductions

Les traductions se trouvent dans src/i18n/ui.ts, avec une structure identique à celle du blog :

src/i18n/ui.ts
export const ui = {
  en: {
    'hero.title': 'Explain your ideas',
    'cta.action': 'Read the docs',
    // ...
  },
  fr: {
    'hero.title': 'Expliquez vos idées',
    'cta.action': 'Lire la documentation',
    // ...
  },
}

Les traductions françaises sont intégrées dans la page au moment du build via define:vars d’Astro et transmises au script en ligne.

Sélecteur de langue

Le LocaleSwitcher de la barre de navigation définit le cookie locale et recharge la page (via onLocaleChange) au lieu de naviguer vers une URL différente. Au rechargement, le script récupère le nouveau cookie et applique les traductions correspondantes.

Sélecteur de langue

Le composant LocaleSwitcher dans la barre de navigation est partagé entre toutes les applications. Il :

  • Affiche la locale actuelle avec un menu déroulant pour en changer
  • Définit un cookie locale sur le domaine racine (par ex. .example.com) afin que le choix persiste entre les sous-domaines
  • Supporte deux modes :
    • Navigation par URL (docs, blog) — suit les liens switchUrls vers les routes préfixées par la locale
    • Rechargement sur place (website) — utilise le callback onLocaleChange pour recharger la page après avoir défini le cookie