Многоязычность и переключение языков
В EpoCanvas Docs встроена полноценная многоязычность на уровне контента: тексты интерфейса — панель навигации, боковая панель, подсказки поиска и другие — и основной текст каждого документа доступны в 10 отдельных языковых версиях. Выбрав язык в правом верхнем углу страницы, читатель переходит к той же статье на выбранном языке: переключаются и основной текст, и интерфейс.
Список поддерживаемых языков
Сейчас сайт предоставляет 10 языков, из которых упрощённый китайский — язык по умолчанию:
| Язык | Название языка | Префикс URL | Аббревиатура в интерфейсе |
|---|---|---|---|
| 简体中文 | Упрощённый китайский (по умолчанию) | без префикса | ZH |
| 繁體中文 | Традиционный китайский | /zh-tw/ | TW |
| English | английский | /en/ | EN |
| 日本語 | японский | /ja/ | JA |
| 한국어 | корейский | /ko/ | KO |
| Español | испанский | /es/ | ES |
| Français | французский | /fr/ | FR |
| Deutsch | немецкий | /de/ | DE |
| Русский | русский | /ru/ | RU |
| Português | португальский | /pt/ | PT |
Список языков определён в SUPPORTED_LANGUAGES в src/utils/i18n.ts, а языковые маршруты зарегистрированы в конфигурации locales в astro.config.mjs; эти два места должны оставаться согласованными.
Как переключить язык
- Найдите справа в верхней панели навигации кнопку языка (на ней показана аббревиатура текущего языка, например
ZH); - Кликните кнопку — в выпадающем меню перечислены все 10 языков;
- Кликните нужный язык (например,
Englishили日本語); - Браузер перейдёт к версии текущей статьи на выбранном языке: навигация, боковая панель, оглавление и основной текст одновременно переключатся на этот язык.

Рисунок: реальный вид с аннотациями после клика по кнопке языка на странице «Многоязычность и переключение языков». ① кнопка переключения языка справа в верхней панели; ② раскрытое выпадающее меню со всеми 10 языками (список прокручивается); ③ текущий активный язык (отмечен галочкой).
Рисунок: порядок выполнения переключения языка. При сборке для каждого языка генерируется свой набор статических страниц; клик по кнопке языка ведёт к той же статье на соответствующем языке; если у отдельных страниц перевод отсутствует, автоматически показывается резервный вариант на китайском.
Правила URL
У каждого языка свой префикс URL; у одной и той же статьи на разных языках различается только префикс:
/canvas/i18n/ → упрощённый китайский (язык по умолчанию, без префикса)/en/canvas/i18n/ → английский/ja/canvas/i18n/ → японский/zh-tw/canvas/i18n/ → традиционный китайский- Информация о языке закодирована прямо в URL: страницу после переключения можно сразу добавлять в закладки и делиться ею, а поисковые системы индексируют языки по отдельности;
- Внутренние ссылки на странице (навигация, боковая панель, рекомендательные ссылки в основном тексте) автоматически получают префикс текущего языка, поэтому при непрерывном чтении в рамках одного языка читатель не возвращается на китайские страницы;
- Каждая языковая версия — отдельная статическая страница, сгенерированная на этапе сборки; атрибут
<html lang>страницы соответствует языку, поэтому скринридеры и средства перевода распознают его корректно.
Что происходит при отсутствии перевода
Отсутствующие переводы система обрабатывает по стратегии «резервный механизм на языке по умолчанию»: если у документа ещё нет перевода на какой-то язык, страница этого языка показывает содержимое на упрощённом китайском по умолчанию, тогда как остальная часть страницы (навигация, боковая панель, тексты интерфейса) остаётся на выбранном языке; ошибки 404 или пустые страницы при этом не появляются.
Преимущество этой стратегии: при добавлении нового документа не нужно ждать готовности переводов на все языки — сначала публикуется китайская версия, а после дополнения переводов достаточно выполнить сборку заново.
Как это реализовано
Многоязычность обеспечивается механизмами интернационализации Astro и Starlight. Процесс сборки выглядит так:
- Каталоги контента разделены по языкам: документы языка по умолчанию лежат в
src/content/docs/(упрощённый китайский), остальные языки — вsrc/content/docs/<язык>/; структура каталогов полностью соответствует китайской, например английская версия «Многоязычность и переключение языков» — этоsrc/content/docs/en/canvas/i18n.md; - При сборке генерируются страницы всех языков:
astro buildчитает конфигурациюlocalesизastro.config.mjsи создаёт полный набор статических страниц для каждого языка; - Интерфейсные строки рендерятся по языкам: тексты интерфейса — навигация в верхней панели, подсказки поиска, заголовки оглавления и т.д. — компоненты выводят на этапе сборки через
getTranslation(key, lang)сразу на нужном языке; скриптов подмены во время выполнения на странице нет; - Внутренние ссылки в тексте локализуются автоматически: плагин
rehypeLocalizeInternalLinksв конвейере сборки автоматически добавляет префикс текущего языка к внутренним ссылкам/canvas/xxxв переведённом тексте; - Полнотекстовый поиск изолирован по языкам: Pagefind строит отдельный индекс для каждого языка, поэтому поиск на английской странице возвращает только английские результаты.
- Изображения в тексте подставляются по языку: плагин
rehypeLocalizeDiagramImagesпереписывает в переводе/images/canvas/<файл>на/images/canvas/<язык>/<файл>, языковые версии лежат вpublic/images/canvas/<язык>/; если файла с тем же именем нет, остаётся оригинал — новое изображение не обязательно сразу готовить на все 10 языков; - Выноски и сноски следуют языку страницы:
rehypeLocalizeAsidesиrehypeLocalizeFootnotesподменяют заголовки выносок и текст сносок по каталогу языка исходника — Starlight определяет язык на этапе remark по абсолютному пути, а локальная сборка передаёт относительный, без этого всё откатывалось бы к китайскому; - hreflang и страница 404: после сборки
hreflangXDefault()добавляет на каждую страницу ссылкуhreflang="x-default"на упрощённую китайскую версию, аsrc/pages/404.astroиспользует тот же словарь, чтобы вывести текст по языку браузера; меню языков на ней ведёт на главную каждого языка.
Для разработчиков: как добавить новый язык
Пример: добавление итальянского языка (Italiano, код it):
- Зарегистрируйте языковой маршрут: добавьте в
localesвastro.config.mjsзаписьit: { label: 'Italiano', lang: 'it' }; - Дополните тексты боковой панели: в
SIDEBAR_I18Nв том же файле добавьте переводыitдля всех групп и пунктов; - Дополните интерфейсные строки: зарегистрируйте язык в
SUPPORTED_LANGUAGESвsrc/utils/i18n.ts(код, название, аббревиатура, префикс URL) и добавьте интерфейсные строки этого языка вUI_TRANSLATIONS; - Переведите содержимое документов: создайте каталог
src/content/docs/it/и разместите в нём переводы, повторяя структуру каталогов китайской версии. Непереведённые страницы сначала показываются на китайском (резервный вариант), их можно дополнять постепенно; Если нужно перевести и снимки интерфейса, создайте каталогpublic/images/canvas/it/с файлами тех же имён — страницы подхватят их сами. - Пересоберите сайт: выполните
pnpm run build— будут сгенерированы страницы нового языка и поисковый индекс. После сборки проверьте структуру перевода и ссылки на изображения командамиnode scripts/audit-i18n.mjsиnode scripts/check-localized-images.mjs; в CI оба checks обязательны.
Для разработчиков: как добавить или изменить интерфейсные строки
Добавляя новый элемент интерфейса, дополните словарь UI_TRANSLATIONS в src/utils/i18n.ts:
// Словарь организован в два уровня «язык → ключ строки», в том же порядке, в котором его читает getTranslationexport const UI_TRANSLATIONS: Record<string, Record<string, string>> = { // Шаг 1: добавьте строки в язык по умолчанию zh-CN (при их отсутствии интерфейс показывает имя ключа) 'zh-CN': { 'nav.plugins': '插件生态', // ...остальные существующие строки }, // Шаг 2: добавьте перевод с тем же ключом для других языков; языки без перевода автоматически откатываются к китайскому en: { 'nav.plugins': 'Plugins', }, ja: { 'nav.plugins': 'プラグイン', },};Затем вызовите getTranslation в компоненте, передав текущий язык:
---import { getLangFromLocale, getTranslation } from '../../utils/i18n';const lang = getLangFromLocale(Astro.currentLocale);---
<a href={localizedHref('/plugins/', lang)}>{getTranslation('nav.plugins', lang)}</a>Интерфейсные строки при сборке рендерятся как статический текст на соответствующем языке, без накладных расходов во время выполнения.