Intermediatei18n25 мин18 апр. 2026 г.

i18n для статических сайтов — 5 локалей

Локализация со слеш-роутами без CMS: словари, динамические пути [locale], hreflang и синхронизация пяти языков.

Архитектура

/en/blog/hello    ← локаль по умолчанию, всё равно с префиксом (чище, чем особый случай)
/ru/blog/hello
/zh/blog/hello
/ja/blog/hello
/de/blog/hello

Три движущиеся части:

  1. Словари — один JSON на локаль, одинаковая форма, типизированная как Record<Locale, typeof en>, чтобы TypeScript вопил, когда ключ разъехался.
  2. Динамические роуты — src/pages/[locale]/... с getStaticPaths(), возвращающей все локали.
  3. Контентный fallback — пиши посты один раз в en/ и рендери их под каждой локалью, пока не появятся переводы.

Типовой трюк, который тебя спасает

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

typeof en — это схема. Добавь ключ в en.json, и билд упадёт, пока остальные четыре словаря не догонят.

Не забудь про head

<link rel="alternate" hreflang="..."> для каждой локали плюс x-default, canonical на каждую страницу и пути, выведенные из Astro.url. Поисковики вознаграждают скучную сантехнику.