Задайте питання та отримайте підсумок документа, вказавши цю сторінку та обраного вами постачальника штучного інтелекту
Історія версій
- "Початкова версія"v9.5.1026.09.2026
Вміст цієї сторінки перекладено за допомогою штучного інтелекту.
Переглянути останню версію оригінального вмісту англійськоюЯкщо у вас є ідея щодо покращення цієї документації, будь ласка, долучіться, надіславши pull request на GitHub.
Посилання на документацію на GitHubСкопіювати документацію у форматі Markdown в буфер обміну
Як інтернаціоналізувати застосунок TanStack Start за допомогою Paraglide JS у 2026 році
Зміст
Що таке Paraglide JS?
Paraglide JS (від inlang) - це бібліотека i18n, побудована на компіляторі. Замість того, щоб поставляти runtime, який шукає ключі в об'єкті JSON, вона компілює кожне повідомлення у типізовану функцію JavaScript (m.about_title()). Невикористані повідомлення можуть бути видалені збіркою (bundler), а друкарська помилка в ключі є помилкою компіляції.
Paraglide - це підхід до i18n, який використовується в офіційних прикладах TanStack Router, і він інтегрується з TanStack Start через три складові:
- плагін Vite, який компілює повідомлення та runtime у
src/paraglide; - серверний middleware, який визначає локаль кожного запиту;
- переписування роутера (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 |
Головні висновки:
- Runtime крихітний, а сторінки не мають витоків. Runtime генерується під вашу конфігурацію, а повідомлення імпортуються там, де вони використовуються.
- Локалі мають витік. Кожна функція повідомлення містить усі локалі, тому приблизно половина перекладених рядків, надісланих на сторінку, припадає на мови, які відвідувач не використовує. Чим більше локалей ви додаєте, тим більшою стає ця частка.
- Завантаження сторінки є найповільнішим у групі, частково тому, що локаль визначається через стратегії під час кожного виклику, а не зчитується з React context.
Перегляньте повні дані: Звіт про бенчмарки TanStack Start, а також репозиторій бенчмарка.
Порівняння функціональності на TanStack Start
Як Paraglide JS виглядає у порівнянні з іншими бібліотеками, що часто використовуються на TanStack Start:
Відкрийте таблицю в модальному вікні, щоб чітко переглянути всі дані
| Можливість | react-intlayer (Intlayer) | use-intl | Paraglide JS | Lingui |
|---|---|---|---|---|
| Переклади поруч із компонентами | ✅ Спільне розташування (Co-located) | ❌ Централізований JSON | ❌ Один файл JSON на локаль | ⚠️ Вихідний текст у компонентах |
| Інтеграція з TypeScript | ✅ Автоматично згенеровані типи | ✅ Через AppConfig | ✅ Типізовані функції повідомлень | ⚠️ Тільки макроси |
| Виявлення відсутніх перекладів | ✅ Помилки типів і попередження збірки | ⚠️ Fallback під час виконання | ⚠️ Fallback до базової локалі | ⚠️ Fallback до вихідного тексту |
| Багатий контент (JSX, Markdown) | ✅ Пряма підтримка | ⚠️ Теги через t.rich | ⚠️ Рядки | ✅ JSX усередині <Trans> |
| Локалізований роутинг | ✅ Вбудовано | ❌ Вручну {-$locale} | ✅ urlPatterns + rewrite роутера | ❌ Вручну {-$locale} |
| Зміна мови без перезавантаження | ✅ Так | ✅ Так | ❌ Повне перезавантаження | ✅ Так |
| Форми множини (Pluralization) | ✅ На основі перелічення | ✅ ICU | ✅ Варіанти | ✅ ICU |
| ICU MessageFormat | ✅ Через format: "icu" | ✅ Нативно | ⚠️ Через плагін inlang | ✅ Нативно |
| Формати контенту | ✅ .ts, .json, .md, .yaml... | ⚠️ .json | ⚠️ inlang JSON | ✅ PO, JSON, CSV |
| Переклад через AI | ✅ Власний провайдер і ключ | ❌ Ні | ❌ Ні | ❌ Ні |
| Візуальний редактор / CMS | ✅ Локальний редактор + опціональна CMS | ❌ Зовнішні платформи | ⚠️ Застосунки екосистеми inlang | ❌ Зовнішні платформи |
| SEO-інструменти (hreflang, sitemap) | ✅ Вбудовано | ❌ Вручну | ⚠️ Локалізовані URL, решта вручну | ❌ Вручну |
| Розмір runtime (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 |
Дані про розмір runtime та витоки взяті з бенчмарка TanStack Start. Витік вимірюється на найкращій конфігурації для кожної бібліотеки.
Інші посібники для TanStack Start: Lingui, use-intl та Intlayer.
Практики, яких варто дотримуватися
- Встановлюйте
langтаdirна тегу<html>на основі визначеної локалі на сервері. - Зберігайте окремий URL для кожної локалі зі стратегією префіксів (
/fr/about), щоб кожна мовна версія індексувалася. - Ставте
urlпершим у вашій стратегії локалей, щоб URL був єдиним джерелом правди, а пошукові роботи отримували саме ту сторінку, яку запитували. - Використовуйте плоскі описові ключі повідомлень (
about_title), які чітко трансформуються в назви функцій. - Фіксуйте в git ваші файли
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. Окремого runtime-пакету встановлювати не потрібно: runtime генерується прямо у вашому проєкті.
Налаштуйте ваші локалі
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Копіювати кодСкопіюйте код у буфер обміну
Форми множини використовують синтаксис варіантів формату повідомлень 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
Необов'язковоЗавдяки переписуванню роутера шлях
/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Копіювати кодСкопіюйте код у буфер обміну
Отримуйте доступ до локалі в Server Functions
Необов'язковоСерверні функції виконуються всередині області видимості middleware Paraglide, тому
getLocale()працює і там:src/server/sendWelcomeEmail.tsКопіювати кодСкопіюйте код у буфер обміну
Порівняйте з Intlayer
Необов'язковоПрямого адаптера з Paraglide на Intlayer немає, оскільки обидві бібліотеки використовують схожу концепцію: компілювати контент під час збірки та поставляти якомога менший runtime. Відмінності полягають у тому, що саме потрапляє до браузера та як організовано контент:
- Локалі: Intlayer завантажує динамічні словники для кожної локалі (0% витоку локалей у бенчмарку), тоді як кожна функція повідомлення Paraglide містить усі локалі (49.7%).
- Організація контенту: контент може знаходитися у файлах
.content.tsпоруч із кожним компонентом або в централізованих файлах. Дивіться локалізація на рівні компонентів проти централізованої i18n. - Перемикання мови: контент зчитується з React context, тому зміна локалі викликає повторний рендеринг без перезавантаження сторінки.
- Згенерований код: усередині
srcнічого не генерується, тому не потрібно нічого повторно генерувати перед комітом.
Якщо ви переходите з іншої бібліотеки, а не з Paraglide, адаптери сумісності зберігають API
use-intl,next-intl,react-i18next,react-intlабо Lingui, замінюючи лише runtime.Дивіться чи є Intlayer легшим за Paraglide? та посібник з Intlayer для TanStack Start.
Автоматизуйте ваші переклади за допомогою Intlayer
Необов'язковоParaglide рендерить переклади, але не допомагає їх створювати. Intlayer є безкоштовним та має відкритий вихідний код, а його інструменти корисні навіть у проєкті з Paraglide:
- Перекладайте за допомогою AI, використовуючи власний ключ API та провайдера. Дивіться автозаповнення та CLI.
- Зберігайте ваші файли JSON як єдине джерело правди за допомогою плагіна синхронізації JSON.
- Тестуйте відсутні переклади у CI. Дивіться тестування перекладів.
- Скануйте ваш розгорнутий сайт на наявність відсутніх
hreflang, неправильних canonical та витоків локалей за допомогою команди scan.
Поширені запитання
Це надійне рішення: воно використовується в офіційних прикладах TanStack Router, має найменший runtime у бенчмарку (~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% витоку локалей.
Коментарі
Поки що немає коментарів. Будьте першим, хто поділиться своїми думками.
