Intermediatei18n25 min18 avr. 2026

i18n pour sites statiques — 5 locales

Localisation par routes slash sans CMS : dictionnaires, routes dynamiques [locale], hreflang, et garder cinq langues synchronisées.

L’architecture

/en/blog/hello    ← locale par défaut, quand même préfixée (plus propre qu'un cas spécial)
/ru/blog/hello
/zh/blog/hello
/ja/blog/hello
/de/blog/hello

Trois pièces mobiles :

  1. Dictionnaires — un JSON par locale, forme identique, typé Record<Locale, typeof en> pour que TypeScript hurle dès qu’une clé dérive.
  2. Routes dynamiques — src/pages/[locale]/... avec getStaticPaths() qui retourne chaque locale.
  3. Fallback de contenu — écris les posts une fois dans en/ et rends-les sous chaque locale en attendant les traductions.

L’astuce de type qui te sauve

export type Locale = "en" | "ru" | "zh" | "ja" | "de";
const dictionaries: Record<Locale, typeof en> = { en, ru, zh, ja, de };

typeof en est le schéma. Ajoute une clé à en.json et le build échoue jusqu’à ce que les quatre autres dictionnaires rattrapent.

N’oublie pas le head

<link rel="alternate" hreflang="..."> pour chaque locale plus x-default, canonical par page, et des chemins dérivés de Astro.url. Les moteurs de recherche récompensent la plomberie ennuyeuse.