Спросите свой вопрос и получите сводку документа, используя эту страницу и выбранного вами поставщика AI
История версий
- "Начальная версия"v9.5.1026.09.2026
Содержимое этой страницы было переведено с помощью ИИ.
Смотреть последнюю версию оригинального контента на английскомЕсли у вас есть идея по улучшению этой документации, не стесняйтесь внести свой вклад, подав запрос на вытягивание на GitHub.
Ссылка на документацию GitHubКопировать Markdown документа в буфер обмена
Как интернационализировать приложение TanStack Start с помощью Lingui в 2026 году
Содержание
Что такое Lingui?
Lingui - это библиотека i18n, построенная вокруг макросов и извлечения сообщений (message extraction). Вы пишете исходный текст прямо в компонентах ( t`Hello` , <Trans>Hello</Trans>), команда lingui extract собирает каждое сообщение в каталоги (по умолчанию PO-файлы), переводчики заполняют их, а плагин Vite компилирует их в компактный JavaScript. Сообщения используют ICU MessageFormat, поэтому поддерживаются множественные числа (plurals) и выборки (selects).
TanStack Start не поставляется со встроенным слоем i18n, поэтому в этом руководстве мы настроим Lingui с нуля:
- Макросы, компилируемые Babel через
@rolldown/plugin-babel(требуется для@vitejs/plugin-reactv6 и Vite 8). - Локализованная маршрутизация с опциональным сегментом
{-$locale}(/about,/fr/about). - Один каталог на локаль, загружаемый по требованию, и отдельный экземпляр
I18nна каждый рендер, чтобы параллельные SSR-запросы никогда не делили одну локаль. - Полное мультиязычное SEO: переведенные
<title>и описание, канонический URL,hreflangсx-default, локали Open Graph, JSON-LD, sitemap,robots.txt, предварительный рендеринг (pre-rendering) и локализованные страницы 404.
Ищете другой стек? Ознакомьтесь с руководством по TanStack Start + use-intl, руководством по TanStack Start + Paraglide или руководством по TanStack Start + Intlayer.
Используете Next.js? См. руководство по Next.js + Lingui. Сравниваете библиотеки? Читайте Lingui против Intlayer.
Что показывают бенчмарки Lingui на TanStack Start
Бенчмарк i18n запускает одинаковое приложение на TanStack Start из 10 страниц и 10 локалей с каждой популярной библиотекой и измеряет то, что реально скачивает браузер.
Динамическая загрузка JSON
Ленивая загрузка переводов во время выполнения
Ограниченный JSON (пространства имен)
Пространства имен перевода для каждой страницы
Бенчмарк производительности I18n
Что это за метрика?
Общий размер пакета библиотеки интернационализации в формате gzip. Он включает в себя только провайдер и логику извлечения контента после tree-shaking и минификации.
Почему это важно?
Меньший размер библиотеки снижает начальную загрузку JavaScript, что ускоряет загрузку и выполнение кода на клиенте.
Вид
Ключевые показатели для @lingui/core@6.6.0, измеренные 2026-09-26 (gzip):
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Конфигурация | Размер библиотеки | JS на страницу | Утечка других локалей | Утечка других страниц |
|---|---|---|---|---|
| Без i18n (базовое приложение) | - | 111.0 KB | 0% | 0% |
| Lingui (настройка из этого гайда) | 56.7 KB | 115.2 KB | 9.3% | 0% |
@intlayer/lingui (совместимость) | 9.8 KB | 136.7 KB | 9.9% | 0% |
react-intlayer (нативный Intlayer) | 4.5 KB | 126.8 KB | 0% | 0% |
Главные выводы:
- Загружайте один каталог на локаль по требованию. Это сохраняет размер страниц близким к базовому приложению.
- Рантайм остается тяжелым (~57 KB gzip). Адаптер совместимости
@intlayer/lingui(шаг 16) сохраняет ваши макросы и сокращает его до ~10 KB.
Ознакомьтесь с полными данными: отчет бенчмарка TanStack Start и репозиторий бенчмарка.
Сравнение возможностей на TanStack Start
Как Lingui соотносится с другими библиотеками, часто используемыми в TanStack Start:
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Возможность | react-intlayer (Intlayer) | use-intl | Paraglide JS | Lingui |
|---|---|---|---|---|
| Переводы рядом с компонентами | ✅ Совместное размещение | ❌ Централизованный JSON | ❌ Один JSON-файл на локаль | ⚠️ Исходный текст в компонентах |
| Интеграция с TypeScript | ✅ Автогенерация типов | ✅ Через AppConfig | ✅ Типизированные функции сообщений | ⚠️ Только макросы |
| Обнаружение отсутствующих переводов | ✅ Ошибки типов и предупреждения сборки | ⚠️ Фолбэк во время выполнения | ⚠️ Фолбэк на базовую локаль | ⚠️ Фолбэк на исходный текст |
| Форматированный контент (JSX, Markdown) | ✅ Прямая поддержка | ⚠️ Теги через t.rich | ⚠️ Строки | ✅ JSX внутри <Trans> |
| Локализованная маршрутизация | ✅ Встроенная | ❌ Вручную {-$locale} | ✅ urlPatterns + rewrite роутера | ❌ Вручную {-$locale} |
| Переключение языка без перезагрузки | ✅ Да | ✅ Да | ❌ Полная перезагрузка страницы | ✅ Да |
| Плюрализация | ✅ На основе перечислений | ✅ ICU | ✅ Варианты | ✅ ICU |
| ICU MessageFormat | ✅ Через format: "icu" | ✅ Нативно | ⚠️ Через плагин inlang | ✅ Нативно |
| Форматы контента | ✅ .ts, .json, .md, .yaml... | ⚠️ .json | ⚠️ inlang JSON | ✅ PO, JSON, CSV |
| AI-перевод | ✅ Свой провайдер и API-ключ | ❌ Нет | ❌ Нет | ❌ Нет |
| Визуальный редактор / CMS | ✅ Локальный редактор + CMS по желанию | ❌ Внешние платформы | ⚠️ Приложения экосистемы inlang | ❌ Внешние платформы |
| SEO-хелперы (hreflang, sitemap) | ✅ Встроенные | ❌ Вручную | ⚠️ Локализованные URL, остальное вручную | ❌ Вручную |
| Размер рантайма (gzip, бенчмарк) | 4.5 KB | 75.9 KB | 1.8 KB | 56.7 KB |
| Утечка, лучшая настройка (локаль / страница) | 0% / 0% | 0% / 0% | 49.7% / 0% | 8.6% / 0% |
| Проверка отсутствующих переводов в CI | ✅ npx intlayer test | ⚠️ Не встроено | ⚠️ Не встроено | ✅ lingui compile --strict |
Показатели размера рантайма и утечек взяты из бенчмарка TanStack Start. Утечка измеряется на оптимальной конфигурации для каждой библиотеки.
Другие руководства по TanStack Start: use-intl, Paraglide JS и Intlayer.
Рекомендуемые практики
- Устанавливайте
langиdirдля<html>на основе локали маршрута, чтобы они были корректными в серверном HTML. - Сохраняйте один URL для каждой локали с префиксом, чтобы каждая языковая версия индексировалась.
- Создавайте один экземпляр
I18nна каждую локаль, никогда не изменяйте глобальный экземпляр во время SSR: два параллельных запроса перезапишут локали друг друга. - Загружайте только активный каталог, никогда не импортируйте все каталоги разом в клиентском коде.
- Выберите один стиль макросов (
useLingui+tв компонентах,msgдля отложенных дескрипторов) и придерживайтесь его. Смешиваниеt,i18n._,i18n.tи<Trans>усложняет чтение кода как для людей, так и для AI-ассистентов. - Запускайте
lingui extractв CI, чтобы новое сообщение никогда не попало в продакшн непереведенным. - Переводите метаданные и объявляйте
canonical,hreflangиx-defaultна каждой странице. - Генерируйте мультиязычные sitemap и robots.txt и выполняйте пререндеринг для каждой локали.
- Используйте реальные ссылки для переключателя языка, чтобы поисковые роботы находили каждую языковую версию.
См. наше руководство по интернационализации и SEO, а также руководство по hreflang.
Пошаговое руководство по настройке Lingui в приложении TanStack Start
Вот структура проекта, которую мы создадим:
Копировать код в буфер обмена
Установка зависимостей
bashКопировать кодКопировать код в буфер обмена
- @lingui/core / @lingui/react: рантайм,
I18nProviderи макросы (@lingui/core/macro,@lingui/react/macro). - @lingui/cli: утилита
lingui extractдля сбора сообщений в каталоги. - @lingui/vite-plugin: компилирует каталоги
.poпри импорте, поэтомуlingui compileвыполнять не требуется. - @lingui/babel-plugin-lingui-macro + @rolldown/plugin-babel: трансформируют макросы во время сборки.
- @lingui/core / @lingui/react: рантайм,
Централизация конфигурации локалей
Локаль по умолчанию остается без префикса (
/about), остальные локали получают префикс (/fr/about).src/i18n/config.tsКопировать кодКопировать код в буфер обмена
Настройка Lingui
Конфигурация Lingui повторно использует тот же список локалей, благодаря чему каталоги, роутер и sitemap всегда согласованы.
lingui.config.tsКопировать кодКопировать код в буфер обмена
Добавьте скрипты извлечения сообщений:
package.jsonКопировать кодКопировать код в буфер обмена
Скрипт
i18n:checkзавершится с ошибкой в CI, если компонент содержит сообщение, которое не было извлечено и закоммичено.Настройка Vite
В
@vitejs/plugin-reactv6 Babel больше не встроен по умолчанию.@rolldown/plugin-babelзапускает плагин макросов Lingui, аlinguiTransformerBabelPresetобрабатывает только файлы, импортирующие макрос, что сохраняет высокую скорость сборки.vite.config.tsКопировать кодКопировать код в буфер обмена
Загрузка каталогов для каждой локали
Шаблонная строка в
import()позволяет Vite создавать отдельный чанк для каждого каталога, а плагин Lingui компилирует файл.poпрямо в него. Посетитель из Франции загружает только французский каталог.Скомпилированные сообщения представляют собой обычные данные, поэтому они могут возвращаться загрузчиком маршрута (loader), сериализоваться в HTML и повторно использоваться при гидратации.
src/i18n/lingui.tsКопировать кодКопировать код в буфер обмена
Чтобы TypeScript распознавал импорт файлов
.po, объявите модуль:src/i18n/po.d.tsКопировать кодКопировать код в буфер обмена
Создание корневого документа
Корневой маршрут считывает опциональный параметр локали для установки атрибутов
langиdirна сервере в теге<html>.src/routes/__root.tsxКопировать кодКопировать код в буфер обмена
Создание маршрута-лейаута локали
Папка
{-$locale}создает опциональный сегмент пути:/aboutи/fr/aboutоба соответствуют/{-$locale}/about. Лейаут отклоняет неизвестные префиксы, загружает каталог текущей локали и предоставляет отдельный экземплярI18n.src/routes/{-$locale}/route.tsxКопировать кодКопировать код в буфер обмена
Использование переводов на страницах
Пишите исходный текст прямо в компоненте. Макросы преобразуют его в идентификаторы сообщений во время сборки, а
lingui extractсобирает их.<Trans>для JSX-контента, включая вложенные элементы;useLingui().tдля строк (атрибуты, пропсы);<Plural>для плюрализации ICU.
src/routes/{-$locale}/about.tsxКопировать кодКопировать код в буфер обмена
Динамический
import()каталога кэшируется системой модулей, поэтому вызовloadI18nв нескольких загрузчиках не скачивает каталог повторно.Извлечение и перевод сообщений
Запустите извлечение. Lingui запишет каждое сообщение в каталог каждой локали:
bashКопировать кодКопировать код в буфер обмена
Затем переведите поле
msgstrдля каждой записи:src/locales/fr/messages.poКопировать кодКопировать код в буфер обмена
src/locales/es/messages.poКопировать кодКопировать код в буфер обмена
По умолчанию идентификаторы сообщений представляют собой хэши исходного текста: изменение текста на английском языке создает новое сообщение. Используйте явные идентификаторы (
<Trans id="about.title">About us</Trans>) для часто меняющихся текстов.Создание компонента LocalizedLink
НеобязательноКаждый маршрут расположен внутри
{-$locale}, поэтому ссылки должны передавать параметр текущей локали.src/components/LocalizedLink.tsxКопировать кодКопировать код в буфер обмена
Смена языка контента
НеобязательноОтображайте переключатель в виде ссылок, чтобы поисковые роботы могли находить все языковые версии. Параметр
to="."сохраняет текущую страницу и заменяет параметр локали. Загрузчик лейаута локали затем получает новый каталог.src/components/LocaleSwitcher.tsxКопировать кодКопировать код в буфер обмена
Интернационализация метаданных
НеобязательноКаждая языковая версия может ранжироваться самостоятельно, если каждая страница предоставляет переведенные
<title>и описание, самоссылающийся канонический URL, одинhreflangна локаль плюсx-default, локали Open Graph и JSON-LD сinLanguage. Метаданные переводятся в загрузчике (шаг 8), а вспомогательная функция формирует остальное:src/i18n/seo.tsКопировать кодКопировать код в буфер обмена
Интернационализация Sitemap и robots.txt
НеобязательноФайл sitemap перечисляет все URL для каждой локали, при этом каждая запись объявляет все свои альтернативные версии с помощью
xhtml:link. Файлrobots.txtблокирует закрытые маршруты для всех языков и указывает на sitemap. Удалитеpublic/robots.txt, если он был создан шаблоном проекта.src/routes/sitemap[.]xml.tsКопировать кодКопировать код в буфер обмена
src/routes/robots[.]txt.tsКопировать кодКопировать код в буфер обмена
Предварительный рендеринг для каждой локали
НеобязательноПеречислите все локализованные пути, чтобы TanStack Start выполнил предварительный рендеринг (prerender) для всех языковых версий во время сборки:
vite.config.tsКопировать кодКопировать код в буфер обмена
Редирект новых посетителей и обработка страниц 404
НеобязательноMiddleware запроса направляет посетителя, перешедшего на
/, на его предпочтительный язык (сначала проверяется cookie, затем заголовокAccept-Language). Прямые ссылки никогда не перенаправляются, поэтому поисковые роботы и пользователи по внешним ссылкам всегда получают запрошенную страницу.src/i18n/negotiateLocale.tsКопировать кодКопировать код в буфер обмена
src/start.tsКопировать кодКопировать код в буфер обмена
Для страниц 404 универсальный catch-all маршрут отрисовывает локализованный
notFoundComponentлейаута. Добавьте директивуnoindex: React 19 автоматически переместит<meta>в<head>.src/components/NotFound.tsxКопировать кодКопировать код в буфер обмена
src/routes/{-$locale}/$.tsxКопировать кодКопировать код в буфер обмена
Сохраните макросы, сократив рантайм с помощью Intlayer
НеобязательноАдаптер совместимости
@intlayer/linguiпозволяет оставить исходный код без изменений: макросы компилируются так же, как и раньше, а результирующие вызовыi18n._(),useLingui()и<Trans>обслуживаются скомпилированными словарями Intlayer. В бенчмарке размер рантайма уменьшается с ~56.7 KB до ~9.8 KB gzip.bashКопировать кодКопировать код в буфер обмена
Добавьте плагин после трансформации макросов, чтобы он сопоставил псевдонимы
@lingui/coreи@lingui/reactс адаптером:vite.config.tsКопировать кодКопировать код в буфер обмена
Каталоги синхронизируются с помощью плагина sync JSON (каталоги JSON) или плагина sync PO (каталоги PO). Подробную настройку смотрите в руководстве по совместимости с Lingui, а прямое сравнение - в статье Lingui против @intlayer/lingui.
Автоматизация переводов с помощью Intlayer
НеобязательноLingui извлекает сообщения, но заполнение десятков каталогов вручную отнимает больше всего времени. Intlayer - бесплатный инструмент с открытым исходным кодом, который работает в связке с Lingui:
- Переводите с помощью AI, используя собственный API-ключ и провайдера. См. автозаполнение и CLI.
- Сохраняйте ваши PO-файлы в качестве единого источника правды с помощью плагина sync PO.
- Проверяйте отсутствие переводов в CI. См. тестирование переводов.
- Проводите аудит развернутого сайта на отсутствие
hreflang, неправильные канонические URL и утечки локалей с помощью команды scan.
Часто задаваемые вопросы
Да. У Lingui нет отдельной официальной интеграции для TanStack Start, но его плагин Vite и плагин макросов Babel работают без изменений. Два ключевых момента, которые нужно настроить правильно: запуск макросов через @rolldown/plugin-babel (Vite 8 и @vitejs/plugin-react v6 больше не включают Babel) и создание отдельного экземпляра I18n на каждую локаль вместо активации глобального экземпляра во время SSR.
На сервере один процесс обрабатывает множество запросов одновременно. Вызов i18n.activate("fr") на общем объекте изменит язык для запроса, параллельно рендерящегося на английском языке. setupI18n создает изолированный экземпляр для каждой локали, что полностью безопасно.
Нет. @lingui/vite-plugin компилирует каталоги .po при их импорте. Вам нужно запускать только lingui extract для сбора новых сообщений.
Объявите их с помощью макроса msg и переведите в загрузчике маршрута с помощью i18n._(msg`...`). Загрузчик возвращает обычные строки, поэтому head() остается синхронной функцией, а значения сериализуются для гидратации. Полная настройка показана на шаге 8 и шаге 12.
Бенчмарк фиксирует размер рантайма ~56.7 KB gzip. При загрузке одного каталога на локаль по требованию страницы весят ~115 KB по сравнению со 111 KB без i18n. Статический импорт всех каталогов сразу увеличивает этот размер до ~152 KB.
Да. Адаптер @intlayer/lingui сохраняет макросы и заменяет рантайм. Затем вы можете постепенно переводить компоненты на useIntlayer по одному. См. адаптеры совместимости.
Комментарии
Пока нет комментариев. Будьте первым, кто поделится своими мыслями.
