Спросите свой вопрос и получите сводку документа, используя эту страницу и выбранного вами поставщика AI
История версий
- "Начальная версия"v9.5.1026.09.2026
Содержимое этой страницы было переведено с помощью ИИ.
Смотреть последнюю версию оригинального контента на английскомЕсли у вас есть идея по улучшению этой документации, не стесняйтесь внести свой вклад, подав запрос на вытягивание на GitHub.
Ссылка на документацию GitHubКопировать Markdown документа в буфер обмена
Как интернационализировать приложение TanStack Start с помощью Paraglide JS в 2026 году
Содержание
Что такое Paraglide JS?
Paraglide JS (от inlang) - это библиотека i18n на основе компилятора. Вместо поставки рантайма, который ищет ключи в объекте JSON, она компилирует каждое сообщение в типизированную JavaScript-функцию (m.about_title()). Неиспользуемые сообщения могут быть удалены сборщиком, а опечатка в ключе приводит к ошибке компиляции.
Paraglide - это подход к i18n, используемый в официальных примерах TanStack Router, и он интегрируется с TanStack Start через три компонента:
- плагин Vite, который компилирует сообщения и рантайм в
src/paraglide; - серверный middleware, определяющий локаль для каждого запроса;
- переписывание маршрутизатора (router rewrite), которое сопоставляет локализованные URL (
/fr/about) с деревом маршрутов (/about), поэтому вам не нужен сегмент$locale.
В этом руководстве настраиваются все три компонента, а затем рассматривается все, что Paraglide оставляет на ваше усмотрение: lang и dir, переключатель локалей, переведенные метаданные, canonical, hreflang с x-default, Open Graph, JSON-LD, sitemap, robots.txt, предварительный рендеринг и локализованные страницы 404.
Ищете другой стек? См. руководство по TanStack Start + use-intl, руководство по TanStack Start + Lingui или руководство по TanStack Start + Intlayer.
Сравниваете два подхода на основе компилятора? Читайте легче ли Intlayer, чем Paraglide?.
Что говорит бенчмарк о Paraglide на TanStack Start
Бенчмарк i18n запускает одно и то же приложение TanStack Start на 10 страниц и 10 локалей с каждой популярной библиотекой и измеряет то, что браузер фактически загружает.
Динамическая загрузка JSON
Ленивая загрузка переводов во время выполнения
Ограниченный JSON (пространства имен)
Пространства имен перевода для каждой страницы
Бенчмарк производительности I18n
Что это за метрика?
Общий размер пакета библиотеки интернационализации в формате gzip. Он включает в себя только провайдер и логику извлечения контента после tree-shaking и минификации.
Почему это важно?
Меньший размер библиотеки снижает начальную загрузку JavaScript, что ускоряет загрузку и выполнение кода на клиенте.
Вид
Ключевые показатели для @inlang/paraglide-js@2.15.1, измеренные 2026-09-26 (gzip):
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Конфигурация | Размер библиотеки | JS на страницу | Утечка других локалей | Утечка других страниц | Загрузка страницы |
|---|---|---|---|---|---|
| Без i18n (базовое приложение) | - | 111.0 KB | 0% | 0% | 15.7 ms |
| Paraglide JS | 1.8 KB | 125.1 KB | 49.7% | 0% | 22.1 ms |
react-intlayer | 4.5 KB | 126.8 KB | 0% | 0% | 14.8 ms |
use-intl | 75.9 KB | 128.7 KB | 0% | 0% | 17.4 ms |
| Lingui | 56.7 KB | 120.2 KB | 8.6% | 0% | 21.9 ms |
Главные выводы:
- Рантайм крошечный, и страницы не утекают. Рантайм генерируется для вашей конфигурации, а сообщения импортируются там, где они используются.
- Локали утекают. Каждая функция сообщения содержит все локали, поэтому около половины переведенных строк, отправляемых на страницу, относятся к языкам, которые посетитель не использует. Чем больше локалей вы добавляете, тем больше становится эта доля.
- Загрузка страницы самая медленная в группе, отчасти потому, что локаль разрешается через стратегии при каждом вызове, а не считывается из контекста React.
Смотрите полные данные: отчет бенчмарка TanStack Start, а также репозиторий бенчмарка.
Сравнение возможностей на TanStack Start
Как Paraglide JS сравнивается с другими библиотеками, часто используемыми на 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 |
| Перевод с помощью ИИ | ✅ Собственный провайдер и ключ | ❌ Нет | ❌ Нет | ❌ Нет |
| Визуальный редактор / 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: Lingui, use-intl и Intlayer.
Практики, которым следует следовать
- Устанавливайте
langиdirдля<html>на основе определенной локали на сервере. - Сохраняйте один URL на локаль со стратегией префиксов (
/fr/about), чтобы каждая языковая версия индексировалась. - Ставьте
urlна первое место в стратегии локалей, чтобы URL был источником истины, а поисковые роботы получали именно запрошенную страницу. - Используйте плоские, описательные ключи сообщений (
about_title), которые аккуратно преобразуются в имена функций. - Фиксируйте в коммитах
messages/*.json, а не сгенерированную папкуsrc/paraglide, чтобы избежать конфликтов слияния в автоматически генерируемых файлах. - Переводите метаданные и объявляйте
canonical,hreflangиx-defaultна каждой странице. - Генерируйте мультиязычный sitemap и robots.txt, а также предварительно рендерите каждую локаль.
- Используйте настоящие ссылки для переключателя локалей, чтобы поисковые роботы могли обнаружить каждый язык.
См. наше руководство по интернационализации и SEO и руководство по hreflang.
Пошаговое руководство по настройке Paraglide JS в приложении TanStack Start
Вот структура проекта, которую мы создадим:
Копировать код в буфер обмена
Обратите внимание, что папки $locale нет: переписывание маршрутизатора удаляет префикс перед сопоставлением маршрутов.
Установите зависимости
Начните с проекта TanStack Start, затем инициализируйте Paraglide. Команда init создает
project.inlang/settings.json, первый файлmessages/en.jsonи устанавливает пакет.bashКопировать кодКопировать код в буфер обмена
- @inlang/paraglide-js: компилятор и его плагин для Vite. Пакет среды выполнения устанавливать не нужно: рантайм генерируется прямо в ваш проект.
Настройте ваши локали
project.inlang/settings.jsonявляется единым источником истины для локалей. Плагин формата сообщений считывает по одному JSON-файлу для каждой локали.project.inlang/settings.jsonКопировать кодКопировать код в буфер обмена
Настройте плагин Vite и стратегию URL
Плагин компилирует сообщения при каждом изменении. Для TanStack Start важны три параметра:
strategy: упорядоченный список мест для извлечения локали. Значениеurlна первом месте делает URL источником истины.cookieиpreferredLanguageиспользуются middleware, когда URL не содержит локали.urlPatterns: как локаль сопоставляется с URL. Локали, отличные от дефолтной, указываются первыми, так как побеждает первый совпавший паттерн. В данном случае локаль по умолчанию остается без префикса (/about), а остальные локали получают префикс (/fr/about).outputStructure: "message-modules": один модуль на каждое сообщение, что позволяет сборщику удалять сообщения, которые страница не импортирует.
vite.config.tsКопировать кодКопировать код в буфер обмена
Добавьте сгенерированную папку в
.gitignore. Она пересоздается приdevиbuild:.gitignoreКопировать кодКопировать код в буфер обмена
Создайте файлы переводов
Каждый ключ становится функцией, экспортируемой из
src/paraglide/messages. Плоские ключи в snake_case дают самые чистые имена функций. Для переменных используются плейсхолдеры{name}.messages/en.jsonКопировать кодКопировать код в буфер обмена
messages/fr.jsonКопировать кодКопировать код в буфер обмена
Для форм множественного числа используется синтаксис вариантов (variants) формата сообщений inlang:
messages/en.jsonКопировать кодКопировать код в буфер обмена
Добавьте серверный middleware
Middleware определяет локаль каждого запроса с помощью вашей стратегии и делает ее доступной для
getLocale()на протяжении всего серверного рендеринга через область видимостиAsyncLocalStorage. Это обеспечивает безопасность параллельных запросов на разных языках.В TanStack Start оберните стандартную точку входа сервера:
src/server.tsКопировать кодКопировать код в буфер обмена
Настройте переписывание локализованных URL в маршрутизаторе
Опция
rewriteв TanStack Router транслирует URL на границе маршрутизатора:- input:
/fr/aboutде-локализуется в/aboutперед сопоставлением, поэтому один маршрутabout.tsxобслуживает все языки; - output: каждый сгенерированный
href(ссылки, редиректы, навигация) локализуется для активной локали, поэтому<Link to="/about">рендерит/fr/aboutна французской странице.
src/router.tsxКопировать кодКопировать код в буфер обмена
Поскольку ссылки локализуются механизмом rewrite, вам не нужен специальный компонент
LocalizedLink: используйте стандартныйLinkиз TanStack Router.- input:
Создайте корневой документ
getLocale()возвращает локаль, определенную middleware на сервере, и локаль из URL в браузере, благодаря чемуlangиdirсовпадают в серверном HTML и после гидратации.src/i18n/config.tsКопировать кодКопировать код в буфер обмена
src/routes/__root.tsxКопировать кодКопировать код в буфер обмена
Используйте переводы на ваших страницах
Сообщения представляют собой обычные функции: импортируйте
m, вызовите функцию, передайте переменные в виде объекта. Все типизировано, включая переменные.src/routes/index.tsxКопировать кодКопировать код в буфер обмена
src/routes/about.tsxКопировать кодКопировать код в буфер обмена
Функция сообщения также принимает явную локаль:
m.about_title({}, { locale: "fr" }). Это полезно в серверном коде, который рендерит язык, отличный от языка запроса (например, в письмах).Смена языка вашего контента
НеобязательноОтображайте переключатель в виде ссылок с помощью
localizeHref, чтобы поисковые роботы могли обнаружить каждый язык.setLocaleсохраняет выбор в cookie и перезагружает страницу на новом языке: полная перезагрузка является ожидаемым поведением Paraglide, поскольку функции сообщений считывают локаль при каждом вызове вместо подписки на состояние React.src/components/LocaleSwitcher.tsxКопировать кодКопировать код в буфер обмена
Интернационализация ваших метаданных
НеобязательноКаждая языковая версия может ранжироваться самостоятельно, если каждая страница предоставляет:
- переведенные
<title>иdescription; - canonical URL, указывающий на саму себя;
- один альтернативный
hreflangдля каждой локали, плюсx-default; - Open Graph
og:locale,og:locale:alternateиog:url; - JSON-LD с
inLanguage.
Функция
localizeUrlиз Paraglide создает альтернативные URL на основе вашихurlPatterns, поэтому они никогда не разойдутся с реальной маршрутизацией:src/i18n/seo.tsКопировать кодКопировать код в буфер обмена
- переведенные
Интернационализация sitemap
НеобязательноМультиязычная карта сайта (sitemap) перечисляет каждый URL для каждой локали, и каждая запись объявляет все свои альтернативы с помощью
xhtml:link:src/routes/sitemap[.]xml.tsКопировать кодКопировать код в буфер обмена
Интернационализация robots.txt
НеобязательноПриватные маршруты существуют на каждом языке, поэтому правила
Disallowдолжны охватывать каждый локализованный путь. Удалитеpublic/robots.txt, если он был создан шаблоном, и отдавайте его через маршрут:src/routes/robots[.]txt.tsКопировать кодКопировать код в буфер обмена
Предварительный рендеринг каждой локали
НеобязательноУкажите локализованный путь для каждой страницы, чтобы TanStack Start предварительно отрендерил все языковые версии. Функция
localizeHrefпредставляет собой сгенерированный код без зависимостей от браузера, поэтому ее можно запускать вvite.config.ts, но этот файл появляется только после первой компиляции. Ручное перечисление путей, как показано ниже, позволяет избежать проблем с порядком сборки:vite.config.tsКопировать кодКопировать код в буфер обмена
Поскольку переключатель отображает настоящие ссылки, параметр
crawlLinks: trueтакже найдет страницы, которые вы забыли указать.Обработка локализованных страниц 404
НеобязательноБлагодаря механизму rewrite путь
/fr/does-not-existсопоставляется как/does-not-exist, аgetLocale()по-прежнему возвращаетfr, поэтому корневойnotFoundComponentиз шага 7 отображается на французском языке. Маршрут catch-all гарантирует, что вложенные пути также попадут на эту страницу. Отметьте страницу тегомnoindex: React 19 переместит<meta>в<head>.src/components/NotFound.tsxКопировать кодКопировать код в буфер обмена
src/routes/$.tsxКопировать кодКопировать код в буфер обмена
Доступ к локали в серверных функциях
НеобязательноСерверные функции выполняются внутри контекста middleware Paraglide, поэтому
getLocale()работает и там:src/server/sendWelcomeEmail.tsКопировать кодКопировать код в буфер обмена
Сравнение с Intlayer
НеобязательноПрямого адаптера для перехода с Paraglide на Intlayer нет, так как обе библиотеки следуют схожей концепции: компиляция контента во время сборки и минимальный объем рантайма. Различия заключаются в том, что попадает в браузер и как организован контент:
- Локали: Intlayer загружает динамические словари для каждой локали (0% утечки локалей в бенчмарке), тогда как каждая функция сообщений Paraglide содержит все локали (49.7%).
- Организация контента: контент может располагаться в файлах
.content.tsрядом с каждым компонентом или в централизованных файлах. См. покомпонентная или централизованная i18n. - Смена локали: контент считывается из контекста React, поэтому смена локали приводит к повторному рендерингу без перезагрузки страницы.
- Генерируемый код: ничего не генерируется внутри
src, поэтому перед коммитом не нужно ничего пересоздавать.
Если вы переходите с другой библиотеки, а не с Paraglide, адаптеры совместимости сохраняют API
use-intl,next-intl,react-i18next,react-intlили Lingui, заменяя только рантайм.См. статью легче ли Intlayer, чем Paraglide? и руководство по Intlayer для TanStack Start.
Автоматизация переводов с помощью Intlayer
НеобязательноParaglide отображает переводы, но не помогает вам создавать их. Intlayer является бесплатным решением с открытым исходным кодом, и его инструменты полезны даже в проекте на Paraglide:
- Переводите с помощью ИИ, используя собственный ключ API и провайдера. См. автозаполнение и CLI.
- Сохраняйте ваши JSON-файлы в качестве источника истины с помощью плагина синхронизации JSON.
- Проверяйте отсутствие переводов в CI. См. тестирование переводов.
- Сканируйте развернутый сайт на предмет отсутствующих тегов
hreflang, неправильных канонических ссылок и утечек локалей с помощью команды scan.
Часто задаваемые вопросы
Это надежный выбор: он используется в официальных примерах TanStack Router, имеет наименьший размер рантайма в бенчмарке (~1.8 KB gzip), а сообщения полностью типизированы. Компромиссы состоят в том, что каждая функция сообщения содержит все локали, из-за чего примерно половина переведенных строк утекает посетителям на других языках, а смена локали перезагружает страницу.
Нет. Механизм rewrite маршрутизатора удаляет префикс локали перед сопоставлением маршрутов и добавляет его обратно к сгенерированным ссылкам, поэтому один файл about.tsx обслуживает /about, /fr/about и /es/about.
Функции сообщений считывают локаль в момент вызова, они не подписаны на состояние React. Поэтому setLocale по умолчанию перезагружает страницу, чтобы каждое сообщение повторно отрендерилось на новом языке. Вы можете передать { reload: false }, но в таком случае вам придется обновить дерево компонентов самостоятельно.
Лучше этого не делать. Папка пересоздается при каждом dev и build, и ее фиксация приводит к конфликтам слияния в сгенерированных файлах. Вместо этого фиксируйте messages/*.json и project.inlang/settings.json.
Используйте localizeUrl для создания одного абсолютного URL для каждой локали в head() маршрута и добавьте x-default, указывающий на базовую локаль. На шаге 10 представлен готовый вспомогательный хелпер, а на шаге 11 эти же альтернативы добавляются в sitemap.
Неиспользуемые сообщения удаляются, если вы используете outputStructure: "message-modules", поэтому контент других страниц не утекает. Неиспользуемые локали не удаляются: каждая функция сообщения содержит все переводы, именно поэтому бенчмарк фиксирует утечку локалей на уровне 49.7%.
Комментарии
Пока нет комментариев. Будьте первым, кто поделится своими мыслями.
