# General Translation Knowledge Base: General Translation vs. nestjs-i18n: ¿cuál deberías usar?
URL: https://generaltranslation.com/es/kb/general-translation-vs-nestjs-i18n.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: nestjs-i18n resuelve el idioma de cada solicitud en una aplicación NestJS y renderiza mensajes a partir de catálogos JSON o YAML por idioma, pero no traduce nada. La CLI de General Translation traduce esos catálogos y su biblioteca gt-node traduce el contenido que solo existe en tiempo de ejecución, así que puedes conservar nestjs-i18n y añadir General Translation.
Category: Internacionalización
Last updated: 2026-10-16
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-16

nestjs-i18n es un módulo de i18n de código abierto para NestJS: determina el idioma de cada solicitud a partir de la cadena de consulta, una cabecera, una cookie o `Accept-Language`, y `I18nContext` o `I18nService` devuelve el mensaje en ese idioma desde tus catálogos. Renderiza traducciones, pero no las genera, así que el catálogo de cada idioma tienes que escribirlo y mantenerlo al día tú, tus traductores o un servicio. General Translation cubre ese vacío de dos formas: su CLI traduce los catálogos de nestjs-i18n y su biblioteca `gt-node` traduce el contenido que solo existe en tiempo de ejecución.

## Lo que nestjs-i18n hace bien

* **Diseñado para Nest.** Una sola llamada a `I18nModule.forRoot()`, [un decorador de parámetro `@I18n()` para `I18nContext` e `I18nContext.current()` en los servicios](https://nestjs-i18n.com/quick-start). Funciona con HTTP, GraphQL, gRPC y WebSockets.
* **Resolvedores de idioma.** [`QueryResolver`, `HeaderResolver`, `CookieResolver` y `AcceptLanguageResolver`](https://nestjs-i18n.com/concepts/resolver) se ejecutan en el orden en que los declares; los resolvedores de GraphQL y gRPC cubren esos transportes, y también puedes escribir los tuyos.
* **Catálogos sencillos.** Una carpeta por idioma (`src/i18n/en/`, `src/i18n/es/`) con [archivos JSON o YAML](https://nestjs-i18n.com/concepts/loader), donde el nombre de cada archivo se convierte en un espacio de nombres (`inbox.title`), además de recarga en caliente durante el desarrollo.
* **Plurales e interpolación.** Marcadores de posición `{name}`, referencias `$t()` a otras claves y [objetos de plural cuyas claves `zero`, `one`, `two`, `few`, `many` y `other`](https://nestjs-i18n.com/guides/plurals) se seleccionan con `Intl.PluralRules`. Como alternativa, la opción `useICU` (de activación voluntaria), [añadida en la versión 10.8.0](https://github.com/toonvanstrijp/nestjs-i18n/releases/tag/v10.8.0), da formato a los mensajes con el formato de mensajes ICU.
* **Seguridad de tipos.** [`typesOutputPath` genera los tipos `I18nTranslations` e `I18nPath`](https://nestjs-i18n.com/guides/type-safety), de modo que una clave mal escrita provoca un error de compilación, y el comando `nestjs-i18n check` termina con un error cuando a un idioma le faltan claves.
* **Mensajes de validación.** `I18nValidationPipe`, `I18nValidationExceptionFilter` e `i18nValidationMessage()` [traducen los errores de class-validator en los DTO](https://nestjs-i18n.com/guides/dto_validation/global-validation).

Tiene licencia MIT y [la versión 10.8.5 requiere Node.js 22 o posterior](https://github.com/toonvanstrijp/nestjs-i18n/blob/v10.8.5/package.json).

## Lo que nestjs-i18n deja en tus manos

Aquí tienes un catálogo en inglés para una bandeja de entrada, con un plural:

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

La carpeta del español contiene una copia traducida del archivo, y un controlador devuelve `i18n.t('inbox.unread', { args: { count } })`. No hay ninguna carpeta para el alemán. Peticiones a una aplicación mínima de Nest 11 con 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."
```

El alemán recurre al inglés porque su catálogo no se ha traducido. La detección de idioma funciona, pero no puede aportar el texto que falta. Ese es el trabajo que nestjs-i18n deja en tus manos: generar los catálogos y mantenerlos al día cada vez que cambia el texto en inglés.

## Cómo encaja General Translation en una app NestJS

La CLI de General Translation traduce los catálogos de nestjs-i18n en su ubicación actual. Haz que una entrada `json` apunte a las carpetas de idioma:

```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) lee `src/i18n/en/inbox.json` y genera `src/i18n/es/inbox.json` y `src/i18n/de/inbox.json`, conservando todas las claves. Ejecútalo en CI y las entradas que no hayan cambiado reutilizarán sus traducciones anteriores. nestjs-i18n carga los catálogos generados mediante su cargador actual.

Este ejemplo usa mensajes en inglés, español y alemán con las formas `one` y `other`. Previsualiza los mensajes generados con recuentos de 1 y 3, y ejecuta `nestjs-i18n check -p src/i18n` para detectar claves faltantes antes del lanzamiento.

Para el contenido que solo existe en tiempo de ejecución, como la publicación de un compañero de equipo o un registro de una base de datos, usa [`gt-node`](/docs/node/quickstart) de General Translation. Inicialízalo una sola vez y luego pasa el idioma resuelto por nestjs-i18n a [`withGT`](/docs/node/reference/functions/with-gt) al llamar a [`tx`](/docs/node/reference/functions/tx):

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

// Lee GT_PROJECT_ID y GT_API_KEY (una clave de proyecto con traducción en tiempo de ejecución) desde el entorno.
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' }) };
    });
  }
}
```

Ahora ambas herramientas usan el idioma que seleccionan tus resolvedores de nestjs-i18n existentes. Si `?lang=es` tiene prioridad sobre `Accept-Language: de`, tanto los mensajes del catálogo como la publicación traducida estarán en español. Usa catálogos para los textos fijos de la interfaz y [`tx`](/docs/node/reference/functions/tx) para el contenido que crean tus usuarios.

Sigue usando nestjs-i18n para las claves tipadas, las búsquedas en catálogos y los mensajes de validación. General Translation se encarga de generar las traducciones y aporta un glosario y prompts personalizados compartidos, además de la [revisión en el panel de control](/docs/platform/dashboard/guides/reviewing-translations). Usa el flujo de trabajo de catálogos descrito arriba para los textos fijos y `tx` para el contenido dinámico.

## nestjs-i18n frente a General Translation de un vistazo

| Característica         | nestjs-i18n                                                                                | General Translation                                                                                              |
| ---------------------- | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| Función                | Resuelve el idioma de la solicitud y renderiza mensajes a partir de catálogos              | Traduce catálogos y también contenido dinámico en tiempo de ejecución                                            |
| Traduce tu contenido   | No                                                                                         | Sí, con [`npx gt translate`](/docs/cli/reference/commands/translate) y [`tx`](/docs/node/reference/functions/tx) |
| Detección de idioma    | Consulta, cabecera, cookie, `Accept-Language`, GraphQL, gRPC y resolvedores personalizados | Usa el mismo idioma resuelto mediante [`withGT`](/docs/node/reference/functions/with-gt)                         |
| Plurales               | Claves de categoría por idioma, seleccionadas con `Intl.PluralRules`                       | Traduce las claves de plural presentes en tu archivo de origen                                                   |
| Seguridad de tipos     | Tipos de claves generados y comprobación de claves faltantes                               | Conserva las claves del catálogo para que sigan valiendo los mismos tipos generados                              |
| Mensajes de validación | Integración con class-validator                                                            | Traduce los catálogos de los que provienen esos mensajes                                                         |
| Costo                  | Gratuito y con licencia MIT                                                                | [Basado en el uso](https://generaltranslation.com/pricing)                                                       |

## Cuándo usar cada uno

Mantén nestjs-i18n por sus resolvedores, sus claves tipadas y su integración con la validación. Añade General Translation si quieres que los catálogos se traduzcan en CI a medida que cambia el texto en inglés, o si tu API devuelve contenido de usuarios o de la base de datos que hay que traducir sobre la marcha. Tus controladores siguen usando las mismas claves; General Translation se encarga de mantener actualizado el texto asociado a ellas.

## Uso de ambos

1. Deja nestjs-i18n y sus carpetas tal como están.
2. Añade `gt.config.json` con la ruta de tu catálogo y define `GT_API_KEY` y `GT_PROJECT_ID`. (Consulta [Configurar la CLI](/docs/cli/guides/configuring#credentials)).
3. Sube las traducciones que ya tienes con [`npx gt upload`](/docs/cli/reference/commands/upload) y, luego, ejecuta [`npx gt translate`](/docs/cli/reference/commands/translate) en CI.
4. Si más adelante editas traducciones locales, ejecuta [`npx gt save-local`](/docs/cli/reference/commands/save-local) antes de volver a generarlas. Añade `gt-node` donde necesites traducción en tiempo de ejecución.

## Conclusiones clave

* nestjs-i18n se encarga de la detección de idioma, las claves tipadas, los plurales y los mensajes de validación en NestJS, pero te toca escribir todos los catálogos en todos los idiomas, incluidas las formas plurales de cada uno.
* La CLI de General Translation traduce los catálogos JSON de nestjs-i18n en el mismo archivo, y `gt-node` traduce el contenido dinámico con el mismo idioma de la solicitud.
* Úsalos juntos: nestjs-i18n renderiza y General Translation traduce.

## Related questions

- [General Translation vs. i18next, react-intl y next-intl: ¿qué biblioteca de i18n deberías usar?](https://generaltranslation.com/es/kb/general-translation-vs-i18n-libraries.mdx): Las bibliotecas de código abierto como i18next, react-intl y next-intl no traducen nada. Muestran las traducciones que tú proporcionas en un archivo de catálogo para cada idioma, escritas por ti, por tus traductores o por un servicio externo. Las bibliotecas de General Translation también son de código abierto y cumplen la misma función, pero además General Translation se encarga de traducir, usando tu código como contexto.
- [¿Por qué usar General Translation en lugar de un TMS (Smartling, Lokalise, Phrase, Crowdin o Transifex)?](https://generaltranslation.com/es/kb/general-translation-vs-tms.mdx): Un sistema de gestión de traducciones (TMS) como Smartling, Lokalise, Phrase, Crowdin o Transifex coordina a los traductores, pero los ingenieros siguen teniendo que extraer las cadenas, enviarlas, esperar las traducciones y volver a integrarlas en el producto. General Translation traduce el contenido de tu código junto con su contexto, incluye todos los idiomas en cada lanzamiento y funciona con bibliotecas de código abierto, sin dependencia de proveedor.
- [¿Deberías crear tu propia i18n o usar General Translation?](https://generaltranslation.com/es/kb/general-translation-vs-in-house-i18n.mdx): Una i18n hecha a mano (un diccionario por idioma y una pequeña función auxiliar t()) funciona bien para uno o dos idiomas y poco texto. A medida que la app crece, acabas reconstruyendo las reglas de plural, las alternativas de respaldo y la sincronización de archivos, y aun así tienes que generar las traducciones. Las bibliotecas de código abierto de General Translation se encargan del renderizado, y General Translation genera y actualiza las traducciones a partir de tu código.
- [General Translation vs. Symfony Translation: ¿cuál deberías usar?](https://generaltranslation.com/es/kb/general-translation-vs-symfony-translation.mdx): Symfony Translation renderiza mensajes en PHP y Twig. General Translation traduce sus catálogos YAML en CI, los mantiene al día a medida que cambia tu contenido de origen y ofrece a los revisores un panel de control para editarlos. Conserva el renderizado de Symfony y añade traducción automatizada a tu flujo de trabajo de lanzamiento.
- [¿Puedo hacer i18n sin archivos de traducción?](https://generaltranslation.com/es/kb/i18n-without-translation-files.mdx): Sí. Con gt-react o gt-next, el contenido se mantiene inline en tus componentes, dentro de un componente `<T>`, y las traducciones se generan en tiempo de compilación, por lo que no tienes que escribir claves ni archivos JSON por configuración regional ni mantenerlos sincronizados.

## Previous and next questions

- Previous question: [General Translation vs. Mobility: ¿cuál deberías usar?](https://generaltranslation.com/es/kb/general-translation-vs-mobility.mdx)
- Next question: [General Translation vs. Paraglide JS: ¿cuál deberías usar?](https://generaltranslation.com/es/kb/general-translation-vs-paraglide.mdx)

## Sitemap

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