Перейти к содержимому

22. Интернационализация (i18n)

Astro предоставляет встроенную поддержку маршрутизации для многоязычных сайтов начиная с версии 3.5. Вместо того чтобы изобретать велосипед или тянуть сторонние библиотеки, вы получаете нативное решение прямо из коробки.

Всё начинается с конфигурации. Определяем локали и язык по умолчанию:

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
i18n: {
defaultLocale: 'ru',
locales: ['ru', 'en', 'ja'],
routing: {
prefixDefaultLocale: false, // /about вместо /ru/about
},
fallback: {
ja: 'en', // японский → английский, если нет перевода
},
},
});

Параметр prefixDefaultLocale: false означает, что страницы на языке по умолчанию будут доступны без префикса: /about, а не /ru/about. Остальные языки получат префикс: /en/about, /ja/about.

После настройки Astro автоматически обрабатывает маршрутизацию:

/ → Главная (русский, по умолчанию)
/en/ → Home (английский)
/ja/ → ホーム (японский)
/about → О нас (русский)
/en/about → About (английский)
/ja/about → 私たちについて (японский)

Структура файлов в src/pages должна отражать эту схему:

src/pages/
├── index.astro ← /
├── about.astro ← /about
├── en/
│ ├── index.astro ← /en/
│ └── about.astro ← /en/about
└── ja/
├── index.astro ← /ja/
└── about.astro ← /ja/about

Для генерации корректных ссылок используйте встроенный хелпер. Он сам добавляет нужный префикс в зависимости от локали:

---
import { getRelativeLocaleUrl } from 'astro:i18n';
const locale = Astro.currentLocale ?? 'ru';
const aboutUrl = getRelativeLocaleUrl(locale, 'about');
const blogUrl = getRelativeLocaleUrl(locale, 'blog');
---
<nav>
<a href={getRelativeLocaleUrl(locale, '/')}>Главная</a>
<a href={aboutUrl}>О нас</a>
<a href={blogUrl}>Блог</a>
</nav>

Если locale = 'en', то getRelativeLocaleUrl('en', 'about') вернёт /en/about. Если locale = 'ru' (default), вернёт /about.

Лучший подход для перевода контента — использовать коллекции с мультиязычной структурой:

src/content/
└── docs/
├── ru/
│ ├── getting-started.md
│ └── installation.md
├── en/
│ ├── getting-started.md
│ └── installation.md
└── ja/
└── getting-started.md

Запрос нужной локали:

import { getCollection } from 'astro:content';
// Получаем все статьи для текущей локали
const locale = Astro.currentLocale ?? 'ru';
const docs = await getCollection('docs', ({ id }) => {
return id.startsWith(locale + '/');
});

Astro предоставляет Astro.currentLocale и Astro.preferredLocale для работы с локалями:

---
const currentLocale = Astro.currentLocale; // 'ru', 'en' или 'ja'
const preferred = Astro.preferredLocale; // из Accept-Language заголовка
const allLocales = Astro.preferredLocaleList; // ['en-US', 'ru', 'ja']
---

Для языков с письмом справа налево (арабский, иврит) достаточно задать направление в HTML:

---
const isRTL = ['ar', 'he', 'fa'].includes(Astro.currentLocale ?? '');
---
<html lang={Astro.currentLocale} dir={isRTL ? 'rtl' : 'ltr'}>