# General Translation Knowledge Base: General Translation или nestjs-i18n: что выбрать?
URL: https://generaltranslation.com/ru/kb/general-translation-vs-nestjs-i18n.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: nestjs-i18n определяет язык каждого запроса в приложении NestJS и выполняет рендеринг сообщений из JSON- или YAML-каталогов для каждого языка, но сам ничего не переводит. CLI General Translation переводит эти каталоги, а библиотека gt-node переводит контент, который появляется только во время выполнения, поэтому можно оставить nestjs-i18n и добавить к нему General Translation.
Category: Интернационализация
Last updated: 2026-10-16
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-16

nestjs-i18n — это модуль i18n с открытым исходным кодом для NestJS: он определяет язык каждого запроса по строке запроса, заголовку, cookie-файлу или `Accept-Language`, а `I18nContext` или `I18nService` возвращает сообщение на этом языке из ваших каталогов. Модуль выполняет рендеринг переводов, но не создаёт их, поэтому каталог для каждого языка пишете и поддерживаете в актуальном состоянии вы сами, ваши переводчики или сторонний сервис. General Translation восполняет этот пробел двумя способами: CLI переводит каталоги nestjs-i18n, а библиотека `gt-node` переводит контент, который появляется только во время выполнения.

## Сильные стороны nestjs-i18n

* **Создан для Nest.** Один вызов `I18nModule.forRoot()`, [декоратор параметра `@I18n()` для `I18nContext` и `I18nContext.current()` в сервисах](https://nestjs-i18n.com/quick-start). Работает поверх HTTP, GraphQL, gRPC и WebSockets.
* **Резолверы языка.** [`QueryResolver`, `HeaderResolver`, `CookieResolver` и `AcceptLanguageResolver`](https://nestjs-i18n.com/concepts/resolver) выполняются в том порядке, в котором вы их указали. Для GraphQL и gRPC предусмотрены отдельные резолверы, а при необходимости можно написать собственный.
* **Простые каталоги.** По одной папке на язык (`src/i18n/en/`, `src/i18n/es/`) с [файлами JSON или YAML](https://nestjs-i18n.com/concepts/loader). Имя каждого файла становится пространством имён (`inbox.title`), а в режиме разработки работает горячая перезагрузка.
* **Формы множественного числа и интерполяция.** Заполнители `{name}`, ссылки `$t()` на другие ключи и [объекты множественного числа с ключами `zero`, `one`, `two`, `few`, `many` и `other`](https://nestjs-i18n.com/guides/plurals), нужный из которых выбирается с помощью `Intl.PluralRules`. Настройка `useICU`, [появившаяся в 10.8.0](https://github.com/toonvanstrijp/nestjs-i18n/releases/tag/v10.8.0) и требующая явного включения, позволяет вместо этого форматировать сообщения с помощью ICU MessageFormat.
* **Типобезопасность.** [`typesOutputPath` генерирует типы `I18nTranslations` и `I18nPath`](https://nestjs-i18n.com/guides/type-safety), поэтому ключ с опечаткой не скомпилируется, а команда `nestjs-i18n check` завершается с ошибкой, если для какого-либо языка не хватает ключей.
* **Сообщения валидации.** `I18nValidationPipe`, `I18nValidationExceptionFilter` и `i18nValidationMessage()` [переводят ошибки class-validator для DTO](https://nestjs-i18n.com/guides/dto_validation/global-validation).

Библиотека распространяется под лицензией MIT, а [версия 10.8.5 требует Node.js 22 или новее](https://github.com/toonvanstrijp/nestjs-i18n/blob/v10.8.5/package.json).

## Что nestjs-i18n оставляет на вас

Вот английский каталог для раздела «Входящие» с формой множественного числа:

```json title="src/i18n/en/inbox.json"
{
  "title": "Inbox",
  "unread": {
    "one": "You have {count} unread message.",
    "other": "You have {count} unread messages."
  }
}
```

В папке для испанского языка лежит переведённая копия файла, а контроллер возвращает `i18n.t('inbox.unread', { args: { count } })`. Папки для немецкого нет. Вот что возвращает минимальное приложение на Nest 11 с nestjs-i18n 10.8.5 на запросы:

```text title="Output"
?lang=es&count=3  "Tienes 3 mensajes sin leer."
?lang=de&count=3  "You have 3 unread messages."
```

Для немецкого языка используется резервный английский, потому что его каталог ещё не переведён. Определение языка работает, но недостающий текст оно взять неоткуда не может. Эту задачу nestjs-i18n оставляет вам: создавать каталоги и обновлять их при каждом изменении английского текста.

## Как General Translation встраивается в приложение NestJS

CLI General Translation переводит каталоги nestjs-i18n прямо на месте. Укажите в записи `json` путь к папкам с языками:

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": [
    "es",
    "de"
  ],
  "files": {
    "json": {
      "include": [
        "src/i18n/[locale]/*.json"
      ]
    }
  }
}
```

[`npx gt translate`](/docs/cli/reference/commands/translate) читает `src/i18n/en/inbox.json` и записывает `src/i18n/es/inbox.json` и `src/i18n/de/inbox.json`, сохраняя все ключи. Запускайте команду в CI — для записей, которые не изменились, будут повторно использованы прежние переводы. nestjs-i18n загружает сгенерированные каталоги через уже настроенный загрузчик.

В этом примере используются сообщения на английском, испанском и немецком языках с формами `one` и `other`. Проверьте сгенерированные сообщения со значениями счётчика 1 и 3, а перед релизом выполните `nestjs-i18n check -p src/i18n`, чтобы найти отсутствующие ключи.

Для контента, который появляется только во время выполнения, например публикации коллеги или записи из базы данных, используйте [`gt-node`](/docs/node/quickstart) от General Translation. Инициализируйте его один раз, а затем при вызове [`tx`](/docs/node/reference/functions/tx) передавайте в [`withGT`](/docs/node/reference/functions/with-gt) язык, разрешённый nestjs-i18n:

```ts title="src/main.ts"
import { NestFactory } from '@nestjs/core';
import { initializeGT } from 'gt-node';
import { AppModule } from './app.module';

// Считывает GT_PROJECT_ID и GT_API_KEY (ключ проекта с поддержкой перевода во время выполнения) из переменных окружения.
initializeGT({ defaultLocale: 'en', locales: ['en', 'es', 'de'] });

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();
```

```ts title="src/posts.controller.ts"
import { Controller, Get, Param } from '@nestjs/common';
import { I18n, I18nContext } from 'nestjs-i18n';
import { tx, withGT } from 'gt-node';
import { PostsService } from './posts.service';

@Controller('posts')
export class PostsController {
  constructor(private readonly posts: PostsService) {}

  @Get(':id')
  async findOne(@Param('id') id: string, @I18n() i18n: I18nContext) {
    return withGT(i18n.lang, async () => {
      const post = await this.posts.findOne(id);
      return { ...post, body: await tx(post.body, { $context: 'A post written by a user' }) };
    });
  }
}
```

Теперь оба инструмента используют язык, который определяют уже настроенные у вас резолверы nestjs-i18n. Если `?lang=es` имеет приоритет над `Accept-Language: de`, то и сообщения из каталога, и переведённый пост будут на испанском. Используйте каталоги для статичных текстов интерфейса, а [`tx`](/docs/node/reference/functions/tx) — для контента, который создают ваши пользователи.

Оставьте за nestjs-i18n типизированные ключи, поиск по ключу в каталоге и сообщения валидации. General Translation берёт на себя генерацию переводов, общий Glossary и пользовательские промпты, а также [проверку переводов в панели управления](/docs/platform/dashboard/guides/reviewing-translations). Для статичных текстов используйте описанный выше рабочий процесс с каталогом, а для динамического содержимого — `tx`.

## nestjs-i18n и General Translation: краткое сравнение

| Возможность                | nestjs-i18n                                                                                             | General Translation                                                                                                    |
| -------------------------- | ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| Роль                       | Разрешает язык запроса и выполняет рендеринг сообщений из каталогов                                     | Переводит каталоги, а также динамическое содержимое во время выполнения                                                |
| Переводит ваш контент      | Нет                                                                                                     | Да, с помощью [`npx gt translate`](/docs/cli/reference/commands/translate) и [`tx`](/docs/node/reference/functions/tx) |
| Определение языка          | Параметр запроса, заголовок, cookie-файл, `Accept-Language`, GraphQL, gRPC и пользовательские резолверы | Использует тот же разрешённый язык через [`withGT`](/docs/node/reference/functions/with-gt)                            |
| Формы множественного числа | Отдельные ключи категорий для каждого языка, выбор через `Intl.PluralRules`                             | Переводит ключи форм множественного числа из вашего исходного файла                                                    |
| Типобезопасность           | Сгенерированные типы ключей и проверка отсутствующих ключей                                             | Сохраняет ключи каталога, поэтому сгенерированные типы остаются прежними                                               |
| Сообщения валидации        | Интеграция с class-validator                                                                            | Переводит каталоги, из которых берутся эти сообщения                                                                   |
| Стоимость                  | Бесплатно, лицензия MIT                                                                                 | [Оплата по факту использования](https://generaltranslation.com/pricing)                                                |

## Когда что использовать

Оставьте nestjs-i18n ради его резолверов, типизированных ключей и интеграции с валидацией. Добавьте General Translation, если хотите, чтобы каталоги переводились в CI по мере изменения английского текста, или если ваш API возвращает пользовательский контент или данные из базы, которые нужно переводить на лету. Существующие контроллеры по-прежнему используют те же ключи, а General Translation следит за тем, чтобы текст за этими ключами оставался актуальным.

## Совместное использование

1. Оставьте nestjs-i18n и его папки без изменений.
2. Добавьте `gt.config.json` с путём к вашему каталогу и задайте `GT_API_KEY` и `GT_PROJECT_ID`. (См. [Настройка CLI](/docs/cli/guides/configuring#credentials).)
3. Загрузите уже имеющиеся переводы с помощью [`npx gt upload`](/docs/cli/reference/commands/upload), а затем запускайте [`npx gt translate`](/docs/cli/reference/commands/translate) в CI.
4. Если в дальнейшем вы будете править переводы локально, перед повторной генерацией выполняйте [`npx gt save-local`](/docs/cli/reference/commands/save-local). Там, где нужен перевод во время выполнения, добавьте `gt-node`.

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

* nestjs-i18n берёт на себя определение языка, типизированные ключи, формы множественного числа и сообщения валидации в NestJS, но все каталоги для всех языков вам придётся писать самостоятельно — включая формы множественного числа для каждого языка.
* CLI от General Translation переводит JSON-каталоги nestjs-i18n на месте, а `gt-node` переводит динамическое содержимое на том же языке запроса.
* Используйте их вместе: nestjs-i18n отвечает за рендеринг, General Translation — за перевод.

## Related questions

- [General Translation против i18next, react-intl и next-intl: какую библиотеку интернационализации выбрать?](https://generaltranslation.com/ru/kb/general-translation-vs-i18n-libraries.mdx): Библиотеки с открытым исходным кодом, такие как i18next, react-intl и next-intl, ничего не переводят. Они лишь отображают переводы, которые вы сами помещаете в файл каталога для каждого языка, — их пишете вы, ваши переводчики или сторонний сервис. Библиотеки General Translation тоже имеют открытый исходный код и делают то же самое, но General Translation ещё и выполняет перевод, используя ваш код как контекст.
- [Почему стоит выбрать General Translation вместо TMS (Smartling, Lokalise, Phrase, Crowdin или Transifex)?](https://generaltranslation.com/ru/kb/general-translation-vs-tms.mdx): Система управления переводами (TMS), например Smartling, Lokalise, Phrase, Crowdin или Transifex, координирует работу переводчиков, но инженерам всё равно приходится извлекать строки, отправлять их на перевод, ждать результатов и встраивать переводы обратно в продукт. General Translation переводит контент прямо в вашем коде с учётом контекста, выпускает все языки с каждым релизом и работает на библиотеках с открытым исходным кодом без привязки к поставщику.
- [Писать собственную i18n или использовать General Translation?](https://generaltranslation.com/ru/kb/general-translation-vs-in-house-i18n.mdx): Самописной i18n (по словарю на каждый язык и небольшой вспомогательной функции t()) вполне достаточно для одного-двух языков и небольшого объёма текста. По мере роста приложения вам приходится заново реализовывать правила множественного числа, резервные варианты и синхронизацию файлов, а переводы всё равно нужно где-то брать. Библиотеки General Translation с открытым исходным кодом берут на себя рендеринг, а General Translation генерирует и обновляет переводы на основе вашего кода.
- [General Translation или Symfony Translation: что выбрать?](https://generaltranslation.com/ru/kb/general-translation-vs-symfony-translation.mdx): Symfony Translation выполняет рендеринг сообщений в PHP и Twig. General Translation переводит его YAML-каталоги в CI, поддерживает их в актуальном состоянии при изменении исходного текста и даёт рецензентам панель управления для их редактирования. Оставьте рендеринг за Symfony и добавьте автоматический перевод в рабочий процесс релиза.
- [Можно ли реализовать i18n без файлов перевода?](https://generaltranslation.com/ru/kb/i18n-without-translation-files.mdx): Да. С gt-react или gt-next контент остаётся встроенным прямо в ваши компоненты внутри компонента `<T>`, а переводы генерируются во время сборки, поэтому не нужно писать ключи и JSON-файлы для каждой локали и следить за их синхронизацией.

## Previous and next questions

- Previous question: [General Translation или Mobility: что выбрать?](https://generaltranslation.com/ru/kb/general-translation-vs-mobility.mdx)
- Next question: [General Translation или Paraglide JS: что выбрать?](https://generaltranslation.com/ru/kb/general-translation-vs-paraglide.mdx)

## Sitemap

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