# General Translation Knowledge Base: Как мигрировать с next-intl на gt-next?
URL: https://generaltranslation.com/ru/kb/migrate-from-next-intl.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Замените плагин, промежуточное ПО и провайдер next-intl на аналоги из gt-next, настройте префикс локали так же, как в next-intl, и загрузите messages/en.json как словарь gt-next, чтобы существующие ICU-сообщения и переводы продолжали работать. Перенесите локализованные пути до удаления маршрутизации next-intl, а затем постепенно, маршрут за маршрутом, переносите тексты прямо в код с помощью `<T>`.
Category: Интернационализация
Last updated: 2026-11-11
Authors: Kevin Wu
Published: 2026-11-11

И next-intl, и gt-next локализуют приложения на Next.js App Router с маршрутами, содержащими префикс локали, и серверными компонентами, поэтому структура приложения почти не меняется. Ваши сообщения next-intl уже написаны в формате ICU MessageFormat — том же, что используют словари gt-next. Благодаря этому при смене библиотеки можно сохранить `messages/en.json` и переведённые каталоги, а затем в удобном темпе переносить тексты прямо в код с помощью [`<T>`](/docs/react/reference/components/t).

Если каталоги вас устраивают и медленно идёт только подготовка переводов, мигрировать, возможно, и не нужно. Если вы остаётесь на next-intl, CLI `gt` переводит его каталоги на месте. (См. [next-intl vs. gt-next](/kb/next-intl-vs-gt-next).)

## Как API next-intl соотносятся с gt-next?

| next-intl                                                                          | gt-next                                                                                                                                                                                                                                                                    |
| ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `defineRouting({ locales, defaultLocale })`                                        | `defaultLocale` и `locales` в `gt.config.json`                                                                                                                                                                                                                             |
| `createNextIntlPlugin()` в `next.config.ts`                                        | [`withGTConfig`](/docs/react/nextjs/config) из `gt-next/config`                                                                                                                                                                                                            |
| `createMiddleware(routing)` в `proxy.ts`                                           | [`createNextMiddleware`](/docs/react/nextjs/reference/functions/create-next-middleware) из `gt-next/middleware`                                                                                                                                                            |
| `localePrefix: 'as-needed'` / `'always'`                                           | `prefixDefaultLocale: false` (по умолчанию) / `true`                                                                                                                                                                                                                       |
| `getRequestConfig` в `i18n/request.ts`                                             | `getLocale.ts` в корневом каталоге, который читает `next/root-params`, плюс опция `dictionary`                                                                                                                                                                             |
| `NextIntlClientProvider`                                                           | [`GTProvider`](/docs/react/reference/components/gt-provider) в `app/[locale]/layout.tsx`                                                                                                                                                                                   |
| `useTranslations('ns')`                                                            | [`useTranslations`](/docs/react/reference/hooks/use-translations)`('ns')` из `gt-next`                                                                                                                                                                                     |
| `await getTranslations('ns')`                                                      | `await` [`getTranslations`](/docs/react/nextjs/reference/functions/get-translations)`('ns')` из `gt-next/server`                                                                                                                                                           |
| `t.rich` и `t.markup`                                                              | [`<T>`](/docs/react/reference/components/t), в который оборачивается сам JSX                                                                                                                                                                                               |
| `useFormatter` / `getFormatter`                                                    | [`<Num>`](/docs/react/reference/components/num), [`<Currency>`](/docs/react/reference/components/currency), [`<DateTime>`](/docs/react/reference/components/datetime) и [`<RelativeTime>`](/docs/react/reference/components/relative-time) либо аргументы ICU в сообщениях |
| [`useLocale` / `getLocale`](https://next-intl.dev/docs/usage/configuration#locale) | [`useLocale`](/docs/react/reference/hooks/use-locale) / [`getLocale`](/docs/react/nextjs/reference/functions/get-locale)                                                                                                                                                   |
| `setRequestLocale(locale)`                                                         | Не нужен для страниц и файлов компоновки при наличии `getLocale.ts`; для обработчиков маршрутов и маршрутов изображений — [`registerLocale`](/docs/react/nextjs/reference/functions/register-locale)                                                                           |
| `Link` из `createNavigation`                                                       | [`Link`](/docs/react/nextjs/link) из `gt-next/link`                                                                                                                                                                                                                        |
| `useRouter` / `getPathname` / `redirect`                                           | Встроенные API Next.js в сочетании с [`useLocalizeHref`](/docs/react/nextjs/reference/hooks/use-localize-href) или [`getLocalizeHref`](/docs/react/nextjs/reference/functions/get-localize-href)                                                                           |
| cookie-файл `NEXT_LOCALE`                                                          | `generaltranslation.locale`; имя можно изменить через `headersAndCookies.localeCookieName`                                                                                                                                                                                 |

## Шаг 1: замените плагин и сохраните сообщения

Установите `gt-next` и CLI `gt`, затем перечислите языки в `gt.config.json`. Направьте `withGTConfig` на существующий каталог исходных сообщений и сохраните структуру URL, как в next-intl:

```ts title="next.config.ts"
import type { NextConfig } from 'next';
import { withGTConfig } from 'gt-next/config';

const nextConfig: NextConfig = {};

export default withGTConfig(nextConfig, {
  dictionary: './messages/en.json',
  prefixDefaultLocale: true, // поведение next-intl по умолчанию: localePrefix: 'always'
  headersAndCookies: { localeCookieName: 'NEXT_LOCALE' }, // запоминает язык вернувшихся посетителей
});
```

Не указывайте `prefixDefaultLocale`, если вы использовали `localePrefix: 'as-needed'`. Задавайте параметры маршрутизации в `withGTConfig`, а не только в промежуточном ПО: `<Link>` из gt-next берёт их именно оттуда.

Этот пример рассчитан на стандартные префиксы локали, например `/de/about`. Если в вызове `defineRouting` маршруты настроены особым образом, перенесите каждую настройку до того, как она будет удалена на шаге 2:

* **Локализованные пути** (`pathnames`, например `/de/ueber-uns`): задайте соответствие для каждого из них с помощью параметра [`pathConfig`](/docs/react/nextjs/reference/functions/create-next-middleware#path-config) в gt-next. Он имеет ту же структуру: общий путь и локализованный путь для каждой локали.
* **Пользовательские префиксы, маршрутизация по доменам или `localePrefix: 'never'`:** в gt-next нет прямого аналога. Определитесь с новыми URL и настройте постоянные перенаправления со старых адресов, прежде чем удалять маршрутизацию next-intl.

Чтобы и дальше использовать уже проверенные переводы, добавьте файл `loadDictionary.ts` в корневой каталог проекта. gt-next обнаружит его автоматически:

```ts title="loadDictionary.ts"
export default async function loadDictionary(locale: string) {
  try {
    return (await import(`./messages/${locale}.json`)).default;
  } catch {
    return {}; // для новой локали без каталога используются переводы General Translation
  }
}
```

Записи в этих файлах имеют приоритет. Для любого ключа, которого нет в каталоге, выполняется рендеринг перевода от General Translation. Если в `gt.config.json` эти каталоги уже указаны в разделе `files`, удалите эту запись: теперь gt-next загружает их как словари, а у каждой строки должен быть только один источник перевода.

## Шаг 2: замените промежуточное ПО, компоновку и конфигурацию запросов

Замените промежуточное ПО next-intl в `proxy.ts` (`middleware.ts` в Next.js 15 и более ранних версиях):

```ts title="proxy.ts"
import { createNextMiddleware } from 'gt-next/middleware';

export default createNextMiddleware();

export const config = {
  matcher: ['/((?!api|static|.*\\..*|_next).*)'],
};
```

Когда маршруты сопоставлены, удалите `i18n/request.ts` и `i18n/routing.ts`. Вместо них добавьте в корневой каталог файл `getLocale.ts`, чтобы для страниц и компоновок работал статический рендеринг без `setRequestLocale`:

```ts title="getLocale.ts"
import { locale } from 'next/root-params';

export default async function getLocale() {
  return await locale();
}
```

Для `next/root-params` требуется Next.js 15.5 или новее; для версий 15.2–15.4 см. [руководство по промежуточному ПО](/docs/react/nextjs/app-router-middleware#root-locale). Затем замените провайдер в файле компоновки локали:

```tsx title="app/[locale]/layout.tsx"
import { GTProvider, getLocales } from 'gt-next';
import { getLocale } from 'gt-next/server';

export function generateStaticParams() {
  return getLocales().map((locale) => ({ locale }));
}

export default async function LocaleLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang={await getLocale()}>
      <body>
        <GTProvider>{children}</GTProvider>
      </body>
    </html>
  );
}
```

По умолчанию, если сегмент локали не поддерживается, gt-next использует `defaultLocale`. Чтобы возвращать 404, как это делает проверка `hasLocale` в next-intl, проверьте сегмент с помощью [`isLocaleSupported`](/docs/react/nextjs/reference/functions/is-locale-supported) и вызовите `notFound()`.

## Шаг 3: Измените инструкции импорта

Если каталог загружен в виде словаря, в большинстве компонентов достаточно изменить только строку import:

```tsx
// До
import { useTranslations } from 'next-intl';
import { getTranslations } from 'next-intl/server';
import { Link } from '@/i18n/navigation';

// После
import { useTranslations } from 'gt-next';
import { getTranslations } from 'gt-next/server';
import Link from 'gt-next/link';
```

`t('heading')`, пространства имён, плейсхолдеры `{name}` и ICU-сообщения с `plural` и `select` работают без изменений, в том числе в `generateMetadata`. Правки потребуются в трёх паттернах:

* **`t.rich` и `t.markup`.** [`t()`](/docs/react/reference/hooks/use-translations) в gt-next возвращает строку. Перенесите форматированный текст непосредственно в [`<T>`](/docs/react/reference/components/t) с настоящими элементами.
* **`t.raw` с массивами.** В gt-next нет `t.raw`, а массив в словаре он воспринимает только как сообщение с параметрами. Преобразуйте списки во вложенные объекты и читайте их через [`t.obj()`](/docs/react/guides/translating-with-dictionaries#objects) или по одному ключу.
* **Отсутствующие ключи.** next-intl пишет ошибку в лог и отображает резервное содержимое, а gt-next выбрасывает исключение, поэтому, прежде чем удалить ключ из каталога, проверьте, где он используется.

Затем запустите [`npx gt validate`](/docs/cli/reference/commands/validate), чтобы найти записи с некорректным ICU, и [`npx gt translate --dictionary ./messages/en.json`](/docs/cli/reference/commands/translate), чтобы создать переводы для ключей, которых нет в ваших каталогах, и для новых локалей. CLI находит словарь автоматически, только если он называется `dictionary.json`, `.ts` или `.js` и лежит в корневом каталоге проекта или в `src/`. Поэтому, пока вы используете этот каталог, передавайте `--dictionary ./messages/en.json` обеим командам — и локально, и в CI:

```bash
npx gt validate --dictionary ./messages/en.json
npx gt translate --dictionary ./messages/en.json
```

## Шаг 4: Перенесите тексты в код, по одному маршруту за раз

Ключи продолжают работать, так что на этом можно остановиться. Чтобы тексты находились рядом с JSX, который их рендерит, переносите их в [`<T>`](/docs/react/reference/components/t) постепенно, маршрут за маршрутом, начиная с сообщений `t.rich`:

```tsx
// Было: "terms": "By continuing you accept the <link>terms</link>."
t.rich('terms', { link: (chunks) => <a href="/terms">{chunks}</a> });

// Стало
<T>
  By continuing you accept the <a href="/terms">terms</a>.
</T>
```

В асинхронных серверных компонентах используйте [`getGT`](/docs/react/nextjs/reference/functions/get-gt) для обычных строк. Та же команда [`npx gt translate`](/docs/cli/reference/commands/translate) создаёт переводы для текста, который вы переносите непосредственно в код, и использует окружающий JSX в качестве контекста. Рецензенты могут исправить эти переводы в [панели управления](/docs/platform/dashboard/guides/reviewing-translations), а Glossary [контекстной группы](/docs/platform/dashboard/guides/defining-context-for-translations) обеспечивает единообразие терминологии. Удаляйте ключи из каталогов, как только они перестают где-либо использоваться.

## Шаг 5: удалите next-intl

Когда поиск по `next-intl` перестанет находить совпадения, удалите зависимость и `createNextIntlPlugin`, а затем проверьте сборку для рабочей среды во всех локалях. После этого добавьте [`npx gt translate`](/docs/cli/reference/commands/translate) в процесс сборки или в [CI](/kb/translations-in-ci), чтобы новые тексты сразу попадали в релиз переведёнными. Если вы сохранили каталог, добавьте флаг `--dictionary ./messages/en.json`.

## Частые вопросы

### Изменятся ли мои URL?

Для стандартных префиксов локали — нет, если вы перенесёте настройку из next-intl: `localePrefix: 'as-needed'` соответствует поведению gt-next по умолчанию, а `'always'` — `prefixDefaultLocale: true`. gt-next также использует сегмент `app/[locale]`. Для локализованных путей требуется явное сопоставление в `pathConfig`, а у пользовательских префиксов и маршрутизации по доменам нет прямого аналога в gt-next. Поэтому настройте перенаправления для таких URL и проверьте все маршруты, прежде чем отключать маршрутизацию next-intl.

### Потеряю ли я существующие переводы?

Нет. Загрузите свои каталоги next-intl с помощью [`loadDictionary`](/docs/react/reference/functions/load-dictionary), и они будут отображаться как прежде. General Translation переведёт только недостающие в них ключи, а также любой текст, который вы позже перенесёте непосредственно в [`<T>`](/docs/react/reference/components/t).

### Поддерживает ли gt-next статический рендеринг?

Да. Добавьте файл `getLocale.ts` в корневой каталог проекта и реализуйте `generateStaticParams`. (См. раздел [Генерация статических сайтов](/docs/react/nextjs/app-router-static-site-generation).)

### gt-next бесплатен?

gt-next распространяется по лицензии MIT и выполняет рендеринг переводов, включённых в сборку, без учётной записи. Генерация переводов с помощью General Translation [оплачивается по факту использования](https://generaltranslation.com/pricing).

## Основные выводы

* Замените плагин, промежуточное ПО, конфигурацию запросов и провайдер next-intl на `withGTConfig`, [`createNextMiddleware`](/docs/react/nextjs/reference/functions/create-next-middleware), `getLocale.ts` и [`GTProvider`](/docs/react/reference/components/gt-provider).
* Оставьте `messages/en.json` в качестве словаря gt-next, а переведённые каталоги подключайте через [`loadDictionary`](/docs/react/reference/functions/load-dictionary); ICU-сообщения работают без изменений.
* Приведите `prefixDefaultLocale` в соответствие с `localePrefix` и сохраните cookie-файл `NEXT_LOCALE`, чтобы стандартные URL локалей и сохранённые предпочтения продолжили работать; перед удалением маршрутизации next-intl перенесите локализованные пути в `pathConfig`.
* Замените `t.rich` на [`<T>`](/docs/react/reference/components/t), а затем постепенно переносите остальной текст непосредственно в код — по одному маршруту за раз.

## Related questions

- [Альтернативы next-intl: gt-next или next-intl](https://generaltranslation.com/ru/kb/next-intl-vs-gt-next.mdx): next-intl выполняет рендеринг переводов, которые вы предоставляете в каталоге сообщений для каждого языка. gt-next тоже выполняет рендеринг переводов, а General Translation, кроме того, генерирует их из текста, написанного прямо в вашем JSX. Обе библиотеки распространяются по лицензии MIT и поддерживают App Router и серверные компоненты. Если ваши каталоги next-intl уже работают, их можно оставить и переводить с помощью General Translation без миграции.
- [Как добавить 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 берут на себя генерацию, проверку и последующие обновления. В этом руководстве также показана явная настройка с локальными файлами.
- [Как настроить SEO для многоязычного приложения Next.js?](https://generaltranslation.com/ru/kb/multilingual-nextjs-seo.mdx): Выделите каждому языку собственный URL с префиксом, например /en/about и /es/about, а затем укажите для каждого опубликованного языка html lang, канонический URL, ссылающийся на саму страницу, альтернативные версии hreflang с x-default, переведённые заголовок и описание, а также запись в карте сайта. Неопубликованные версии пометьте noindex. gt-next от General Translation направляет каждый язык на собственный URL и переводит заголовки с помощью getGT.
- [Языковые перенаправления и SEO: URL, cookie-файл или Accept-Language?](https://generaltranslation.com/ru/kb/locale-routing-seo.mdx): Язык каждой страницы, которую вы хотите видеть в индексе, должен определять URL, ведь Googlebot не отправляет заголовок Accept-Language и сканирует сайты в основном с американских адресов. Сохранённый в cookie-файле выбор, а за ним Accept-Language используйте только для того, чтобы решить, куда перенаправлять с нейтрального корневого пути вроде /, причём временным перенаправлением 302 или 307.
- [Как поддерживать переводы в актуальном состоянии при каждом развёртывании?](https://generaltranslation.com/ru/kb/translations-in-ci.mdx): Запускайте перевод как этап конвейера перед каждой сборкой для рабочей среды — тогда новые тексты попадут в то же развёртывание, что и сами изменения, уже переведёнными. В CLI gt от General Translation для этого служит команда npx gt translate, которая использует ключ API проекта и идентификатор проекта, сохранённые как секреты CI.

## Previous and next questions

- Previous question: [Какие инструменты перевода берут плату за использование, а не за места?](https://generaltranslation.com/ru/kb/translation-pricing-without-seat-fees.mdx)
- Next question: [Как мигрировать с react-i18next на gt-react?](https://generaltranslation.com/ru/kb/migrate-from-react-i18next.mdx)

## Sitemap

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