# General Translation Knowledge Base: Как добавить i18n в TanStack Start?
URL: https://generaltranslation.com/ru/kb/add-i18n-to-tanstack-start.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: В TanStack Start нет встроенной поддержки i18n, поэтому нужно подключить библиотеку, которая разрешает локаль для каждого серверного запроса — обычно по префиксу URL или cookie-файлу — и загружает сообщения до рендеринга. Paraglide JS, react-i18next и Lingui выполняют рендеринг переводов, которые вы готовите сами; экспериментальный gt-tanstack-start от General Translation, кроме того, генерирует их из текста, встроенного прямо в JSX.
Category: Интернационализация
Last updated: 2026-10-28
Authors: General Translation Team
Published: 2026-10-28

В TanStack Start нет слоя i18n, поэтому три составляющие придётся добавить самостоятельно: библиотеку, которая выполняет рендеринг текста на активном языке, способ разрешать этот язык при каждом серверном запросе и сами переводы. Start выполняет рендеринг всего документа на сервере, а затем гидратирует его в браузере, поэтому обеим сторонам нужны одна и та же локаль и одни и те же сообщения — иначе первая отрисовка окажется не на том языке или гидратация завершится ошибкой.

## Что даёт TanStack Start, а что остаётся на вас

TanStack Start — это «full-stack React-фреймворк на базе TanStack Router» с серверным рендерингом всего документа (SSR), потоковой передачей, серверными функциями и промежуточным ПО для запросов ([обзор TanStack Start](https://tanstack.com/start/latest/docs/framework/react/overview)). Некоторые из этих возможностей служат основой для настройки i18n:

* **URL с локалью.** Необязательный параметр пути, например `/{-$locale}/about`, позволяет одному файлу маршрута обрабатывать `/about`, `/es/about` и `/fr/about`. Как альтернатива, опция `rewrite` роутера может добавлять и удалять префикс локали ([руководство по i18n в TanStack Router](https://tanstack.com/router/latest/docs/guide/internationalization-i18n)).
* **Промежуточное ПО для запросов.** Промежуточное ПО, зарегистрированное через `createStart` в `src/start.ts`, выполняется перед каждым запросом, включая SSR и серверные функции ([промежуточное ПО TanStack Start](https://tanstack.com/start/latest/docs/framework/react/guide/middleware)). Именно здесь библиотека интернационализации считывает URL, cookie-файл или заголовок `Accept-Language`.
* **Загрузчики и `head`.** Загрузчик корневого маршрута может загрузить сообщения для локали до рендеринга, а `head` каждого маршрута задаёт переведённый `<title>` и метатеги.

Что Start оставляет на вас: каталоги сообщений и среду выполнения, которая ищет в них строки; определение локали и cookie-файл, запоминающий выбор пользователя; атрибут `<html lang>` в корневой оболочке; форматирование множественного числа и чисел; ссылки `hreflang`, а также сами переводы. В руководстве TanStack по i18n подробно описан Paraglide JS, включая настройку SSR для TanStack Start, и есть ссылки на руководства сообщества по Intlayer и use-intl. Кроме того, в TanStack CLI есть дополнение `paraglide` для новых приложений.

## Доступные варианты

| Библиотека                                                   | Как пишется текст                                                                                                        | Локаль на сервере                                                                                                                                                                             | Откуда берутся переводы                                                                                              |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| [Paraglide JS](https://paraglidejs.com/tanstack-start)       | Сообщения в JSON-файлах для каждой локали, компилируемые в типизированные функции, например `m.greeting()`               | `paraglideMiddleware` оборачивает серверный обработчик; доступны стратегии по URL, cookie-файлу и предпочитаемому языку                                                                       | Вы, переводчики или команда машинного перевода, которую вы запускаете для файлов                                     |
| [react-i18next](https://react.i18next.com/latest/ssr)        | Ключи в пространствах имён JSON, с рендерингом через `t('home.title')`                                                       | В документации нет интеграции с TanStack Start; вы сами создаёте экземпляр для каждого запроса (per-request) и передаёте клиенту `initialLanguage` и `initialI18nStore`                       | Вы, переводчики или система управления переводами (TMS), например Locize                                             |
| [Lingui](https://lingui.dev/ref/vite-plugin)                 | Встроенные макросы `<Trans>`, извлекаемые в каталоги PO                                                                  | Плагин для Vite компилирует каталоги; вы активируете локаль запроса на сервере и в браузере                                                                                                   | Вы, переводчики или сервис, синхронизируемый с каталогами                                                            |
| General Translation (`gt-tanstack-start`, экспериментальная) | JSX, обёрнутый в [`<T>`](/docs/react/reference/components/t), строки через [`useGT`](/docs/react/reference/hooks/use-gt) | [`gtMiddleware`](/docs/react/tanstack-start/reference/functions/gt-middleware): префикс URL (требует явного включения), затем cookie-файл, затем `Accept-Language`, затем локаль по умолчанию | Генерируются командой [`npx gt translate`](/docs/cli/reference/commands/translate) и проверяются в панели управления |

Выбирайте Paraglide JS, если вам нужны настройка из документации TanStack, типизированные функции сообщений и tree-shaking на уровне отдельных сообщений, а способ заполнять JSON-файлы у вас уже есть. Выбирайте react-i18next, если переносите каталоги i18next из другого приложения. Выбирайте Lingui, если ваши переводчики работают с файлами PO. Выбирайте General Translation, если хотите, чтобы текст оставался прямо в компонентах, а переводы генерировались на его основе и автоматически поддерживались в актуальном состоянии. (Подробное сравнение см. в статье [General Translation vs. Paraglide JS](/kb/general-translation-vs-paraglide).)

`gt-tanstack-start` — экспериментальная библиотека: в документации General Translation указано, что в ней возможны несовместимые изменения и использовать её в рабочей среде пока не рекомендуется. Стабильный вариант настройки для React см. в статье [Как перевести React-приложение?](/kb/translate-react-app).

## Добавление General Translation в TanStack Start

В этом пошаговом руководстве мы добавим на страницу испанский и французский языки, переведём серверную функцию, а затем вынесем каждый язык на отдельный URL. Руководство проверено на приложении, созданном командой `npx @tanstack/cli@latest create` (`@tanstack/react-start` 1.169.4), с `gt-tanstack-start@11.4.16` и `gt@2.26.11`. Пакету требуется `@tanstack/react-start` версии 1.159.0 или новее; он поддерживает только ESM.

[Мастер настройки](/docs/cli/reference/commands/init) `npx gt@2.26.11 init` вносит те же изменения, что и шаги 1–4: устанавливает пакет, создаёт загрузчик, промежуточное ПО, вызов роутера и корневой маршрут, а также выводит список всего, что не может безопасно изменить сам. Проверьте различия, которые он внёс, или выполните шаги вручную.

### 1. Установите библиотеку и CLI

```bash
npm install gt-tanstack-start@11.4.16
npm install --save-dev gt@2.26.11
```

`gt-tanstack-start` экспортирует общие компоненты React, такие как [`<T>`](/docs/react/reference/components/t) и [`<LocaleSelector>`](/docs/react/reference/components/locale-selector), а также серверные вспомогательные функции. CLI `gt` находит исходные тексты в вашем коде и создаёт файлы перевода.

### 2. Укажите языки

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["es", "fr"],
  "files": {
    "gt": {
      "output": "src/_gt/[locale].json"
    }
  }
}
```

Размещайте выходные файлы в `src/`, чтобы Vite мог их импортировать. Затем добавьте загрузчик:

```ts title="src/loadTranslations.ts"
export default async function loadTranslations(locale: string) {
  const translations = await import(`./_gt/${locale}.json`);
  return translations.default;
}
```

### 3. Зарегистрируйте промежуточное ПО для обработки запросов

```ts title="src/start.ts"
import { createCsrfMiddleware, createStart } from '@tanstack/react-start';
import { gtMiddleware } from 'gt-tanstack-start';

// Сохраняем защиту TanStack Start от CSRF для серверных функций.
const csrfMiddleware = createCsrfMiddleware({
  filter: ({ handlerType }) => handlerType === 'serverFn',
});

export const startInstance = createStart(() => ({
  requestMiddleware: [csrfMiddleware, gtMiddleware],
}));
```

[`gtMiddleware`](/docs/react/tanstack-start/reference/functions/gt-middleware) от General Translation разрешает локаль один раз для каждого запроса — сначала по cookie-файлу локали, затем по `Accept-Language`, затем по `defaultLocale` — и сохраняет её в cookie-файле. Каждый запрос сохраняет собственную локаль, даже если рендеринг нескольких запросов выполняется одновременно.

### 4. Инициализируйте библиотеку и выполните гидратацию корневого маршрута

Добавьте инициализатор в существующий файл `src/router.tsx` на уровне области видимости модуля:

```tsx title="src/router.tsx"
import { initializeGT } from 'gt-tanstack-start';
import gtConfig from '../gt.config.json';
import loadTranslations from './loadTranslations';

initializeGT({ ...gtConfig, loadTranslations });

// ... ваша текущая функция getRouter()
```

Затем загрузите локаль и её переводы в корневом маршруте и передайте их в [`<GTProvider>`](/docs/react/reference/components/gt-provider):

```tsx title="src/routes/__root.tsx"
import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router';
import {
  GTProvider,
  LocaleSelector,
  getLocale,
  getTranslationsSnapshot,
} from 'gt-tanstack-start';

export const Route = createRootRoute({
  // Выполняется на сервере при первом запросе, поэтому HTML приходит уже переведённым.
  loader: async () => {
    const locale = getLocale();
    return { locale, translations: await getTranslationsSnapshot(locale) };
  },
  shellComponent: RootDocument,
});

function RootDocument({ children }: { children: React.ReactNode }) {
  const { locale, translations } = Route.useLoaderData();
  return (
    <html lang={locale}>
      <head>
        <HeadContent />
      </head>
      <body>
        <GTProvider locale={locale} translations={translations}>
          <LocaleSelector />
          {children}
        </GTProvider>
        <Scripts />
      </body>
    </html>
  );
}
```

[`getLocale`](/docs/react/tanstack-start/reference/functions/get-locale) считывает локаль запроса на сервере и cookie-файл в браузере, поэтому результаты рендеринга на сервере и клиенте совпадают. Атрибут `lang={locale}` заменяет жёстко заданный `lang="en"` в оболочке стартового шаблона.

### 5. Пометьте контент для перевода

```tsx title="src/routes/index.tsx"
import { createFileRoute } from '@tanstack/react-router';
import { T, useGT } from 'gt-tanstack-start';

export const Route = createFileRoute('/')({ component: Home });

function Home() {
  const gt = useGT();

  return (
    <main>
      <T>
        <h1>Find your next project</h1>
        <p>Explore projects from teams around the world.</p>
      </T>
      <input type="search" placeholder={gt('Search projects')} aria-label={gt('Search projects')} />
    </main>
  );
}
```

[`<T>`](/docs/react/reference/components/t) переводит заголовок и абзац как единое целое, используя разметку в качестве контекста. [`useGT`](/docs/react/reference/hooks/use-gt) отвечает за строки в атрибутах. Для имён, чисел и дат внутри [`<T>`](/docs/react/reference/components/t) используйте [компоненты переменных и форматирования](/docs/react/guides/formatting-variables).

### 6. Создайте переводы

Войдите в систему с помощью [`npx gt login`](/docs/cli/reference/commands/login), задайте `GT_PROJECT_ID` (или `projectId` в `gt.config.json`) и выполните [`npx gt translate`](/docs/cli/reference/commands/translate). Команда создаст файлы `src/_gt/es.json` и `src/_gt/fr.json`. Генерация оплачивается [по факту использования](https://generaltranslation.com/pricing).

Чтобы опробовать настройку без учётной записи, выполните [`npx gt generate`](/docs/cli/reference/commands/generate). Команда создаст те же файлы с исходным текстом на английском языке, который затем можно отредактировать вручную. Для локали, у которой ещё нет файла, выполняется рендеринг исходного текста, а в журнал записывается предупреждение о том, что не удалось загрузить переводы.

### 7. Запустите приложение и переключите язык

Выполните `npm run dev` и выберите Español в переключателе. Выбор сохранится в cookie-файле локали, страница перезагрузится, и сервер выполнит рендеринг на испанском. В тестовом приложении сборка для рабочей среды возвращала `<html lang="es">` с испанским заголовком и плейсхолдером на запрос с `Accept-Language: es`, а на запрос без языковых предпочтений — `<html lang="en">` с текстом на английском.

## Перевод в серверных функциях и метаданных

[`getGT`](/docs/react/tanstack-start/reference/functions/get-gt) переводит строки внутри серверной функции с учётом локали запроса:

```tsx title="src/routes/account.tsx"
import { createFileRoute } from '@tanstack/react-router';
import { createServerFn } from '@tanstack/react-start';
import { getGT } from 'gt-tanstack-start';

const loadAccount = createServerFn({ method: 'GET' }).handler(async () => {
  const gt = await getGT();
  return { title: gt('Your account') };
});

export const Route = createFileRoute('/account')({
  loader: () => loadAccount(),
  // Переведённый заголовок также используется как <title> страницы.
  head: ({ loaderData }) => ({ meta: [{ title: loaderData?.title }] }),
  component: () => <h1>{Route.useLoaderData().title}</h1>,
});
```

На сервере эти вспомогательные функции выбрасывают ошибку, если вызываются вне запроса, обработанного [`gtMiddleware`](/docs/react/tanstack-start/reference/functions/gt-middleware), — например, в области видимости модуля. Записи словаря и зарегистрированные сообщения также рассматриваются в разделе [Использование серверных функций](/docs/react/tanstack-start/using-server-functions).

## Отдельный URL для каждого языка

При описанной выше настройке все языки доступны по одному и тому же URL, а язык определяется по cookie-файлу или языку браузера. Поисковые системы индексируют только один язык для каждого URL, поэтому [публичным страницам нужен префикс](/kb/locale-routing-seo), например `/es/about`. Перенесите маршруты в необязательный сегмент — например, `src/routes/{-$locale}/index.tsx` с `createFileRoute('/{-$locale}/')`, — а затем включите маршрутизацию по локалям:

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["es", "fr"],
  "localeRouting": true
}
```

После этого промежуточное ПО сначала проверяет путь, а переключатель языка ведёт на URL с префиксом. В тестовом приложении `/es` и `/es/account` проходили рендеринг на испанском с `<html lang="es">`, а `/` — на английском. Для вернувшегося посетителя URL без префикса по-прежнему определяется по cookie-файлу, а [ссылки `hreflang`](/kb/what-is-hreflang) в `head` каждого маршрута нужно добавить самостоятельно. (См. [настройку маршрутизации по локалям](/docs/react/tanstack-start/setup#locale-routing).)

## Публикация и актуализация переводов

Запускайте перевод перед каждой сборкой, чтобы новые тексты сразу выходили на всех языках:

```json title="package.json"
{
  "scripts": {
    "build": "gt validate && gt translate && vite build"
  }
}
```

[`gt validate`](/docs/cli/reference/commands/validate) прерывает сборку, если контент может сломать перевод, ещё до каких-либо вызовов API. В CI задайте `GT_PROJECT_ID` и ключ API проекта в `GT_API_KEY` с правами **Files &gt; Write** и **Translation queue &gt; Enabled** ([учётные данные CLI](/docs/cli/guides/configuring#credentials)). При последующих запусках переводится только новый или изменённый исходный текст.

Рецензенты могут отредактировать любую строку в [Редакторе переводов](/docs/platform/dashboard/guides/reviewing-translations) General Translation, а [`npx gt save-local`](/docs/cli/reference/commands/save-local) отправляет обратно правки, внесённые в JSON-файлы, чтобы они сохранялись при последующих запусках. [Контекстная группа](/docs/platform/dashboard/guides/defining-context-for-translations) хранит ваш Glossary и пользовательские промпты, благодаря чему названия продуктов и тон остаются единообразными в этом приложении, вашей документации и других проектах. [Locadex](/docs/platform/locadex/guides/configuring-automations), AI-агент General Translation, поддерживает приложения на TanStack Start и может переводить новые тексты через пул-реквесты.

## Часто задаваемые вопросы

### Есть ли в TanStack Start встроенная поддержка i18n?

Нет. TanStack Router предоставляет необязательные сегменты локали в URL и перезапись URL, а Start — промежуточное ПО и загрузчики, но сообщения, определение локали и переводы берутся из сторонней библиотеки.

### Можно ли использовать react-i18next с TanStack Start?

Да, как обычную React-библиотеку. В документации TanStack это не описано, а руководство react-i18next по SSR упоминает только интеграции с Next.js, Remix и Gatsby, поэтому создание per-request экземпляра и гидратацию на клиенте придётся настроить самостоятельно.

### Готов ли gt-tanstack-start к использованию в рабочей среде?

Пока нет: General Translation считает его экспериментальным. Зафиксируйте версию и перед обновлением обязательно просматривайте журнал изменений.

## Ключевые выводы

* В TanStack Start нет собственного слоя i18n; подключить его можно через необязательные сегменты `/{-$locale}`, промежуточное ПО `createStart` и корневые загрузчики.
* Разрешайте локаль на сервере для каждого запроса, гидратируйте клиент теми же сообщениями и задавайте `<html lang>` из загрузчика вместо жёстко прописанного в стартовом шаблоне `lang="en"`.
* Paraglide JS — библиотека, которую описывает документация TanStack; и она, и react-i18next, и Lingui лишь выполняют рендеринг переводов, которые вы предоставляете сами.
* Экспериментальный пакет `gt-tanstack-start` от General Translation добавляет [`gtMiddleware`](/docs/react/tanstack-start/reference/functions/gt-middleware), [`initializeGT`](/docs/react/reference/config#initialize) и [`<GTProvider>`](/docs/react/reference/components/gt-provider), позволяет хранить тексты прямо в коде внутри [`<T>`](/docs/react/reference/components/t), а [`npx gt translate`](/docs/cli/reference/commands/translate) записывает переводы в `src/_gt/[locale].json`.
* Добавьте `"localeRouting": true` вместе с необязательным сегментом `{-$locale}`, если каждому языку нужен собственный индексируемый URL.

## Related questions

- [Как добавить i18n в приложение Next.js на App Router?](https://generaltranslation.com/ru/kb/add-i18n-to-nextjs.mdx): Начните с gt init, чтобы настроить General Translation в поддерживаемом проекте на App Router, затем разметьте исходное содержимое, создайте переводы и проверьте переключение языка. gt-next хранит тексты прямо в JSX вместе с контекстом перевода, а CLI, редактор в панели управления и Locadex берут на себя генерацию, проверку и последующие обновления. В этом руководстве также показана явная настройка с локальными файлами.
- [General Translation или Paraglide JS: что выбрать?](https://generaltranslation.com/ru/kb/general-translation-vs-paraglide.mdx): Выбирайте General Translation, если хотите держать тексты прямо в коде и создавать переводы с учётом структуры ваших React-компонентов, общей терминологии и проверки в панели управления. Выбирайте Paraglide JS, если вам нужны скомпилированные типизированные функции сообщений и tree-shaking на уровне отдельных сообщений. Paraglide выполняет рендеринг ваших каталогов, а General Translation связывает исходные тексты с созданием переводов и их последующим обновлением.
- [Какая библиотека интернационализации лучше всего подходит для приложения React?](https://generaltranslation.com/ru/kb/best-react-i18n-library.mdx): Четыре основные библиотеки интернационализации для React — это gt-react от General Translation, react-i18next, Lingui и React Intl. Все четыре выполняют рендеринг и форматирование переводов, но только gt-react ещё и генерирует их — на основе текста, написанного прямо в JSX. Выбирайте react-i18next, если хотите сохранить каталоги и плагины i18next, Lingui — если нужно извлечение текста в скомпилированные каталоги, а React Intl — если вам нужны FormatJS и ICU MessageFormat.
- [Языковые перенаправления и SEO: URL, cookie-файл или Accept-Language?](https://generaltranslation.com/ru/kb/locale-routing-seo.mdx): Язык каждой страницы, которую вы хотите видеть в индексе, должен определять URL, ведь Googlebot не отправляет заголовок Accept-Language и сканирует сайты в основном с американских адресов. Сохранённый в cookie-файле выбор, а за ним Accept-Language используйте только для того, чтобы решить, куда перенаправлять с нейтрального корневого пути вроде /, причём временным перенаправлением 302 или 307.
- [Как перевести React-приложение?](https://generaltranslation.com/ru/kb/translate-react-app.mdx): Перевод React-приложения состоит из двух этапов — интернационализации компонентов, чтобы они отображались на языке пользователя, и перевода каждой строки на все поддерживаемые языки. gt-react от General Translation переводит JSX на месте в компоненте `<T>`, а npx gt translate создаёт по одному файлу на каждый язык.

## Previous and next questions

- Previous question: [Альтернативы Weglot: General Translation и Weglot](https://generaltranslation.com/ru/kb/general-translation-vs-weglot.mdx)
- Next question: [Как добавить i18n в приложение Next.js на Pages Router?](https://generaltranslation.com/ru/kb/add-i18n-to-nextjs-pages-router.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/ru/kb/sitemap.md) for every article.
