# General Translation Knowledge Base: ¿Deberías crear tu propia i18n o usar General Translation?
URL: https://generaltranslation.com/es/kb/general-translation-vs-in-house-i18n.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: 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.
Category: Internacionalización
Last updated: 2026-10-16
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-16

Puedes implementar la internacionalización (i18n) por tu cuenta: un objeto de mensajes por idioma, una función auxiliar `t()` que busca una clave y rellena las variables, un selector de configuración regional y las API integradas de `Intl` para números y fechas. Para uno o dos idiomas y unas cuantas docenas de cadenas, muchas veces no necesitas nada más, y es justo lo que suele escribir un agente de programación cuando le pides que añada un idioma. Lo que crece con la app es todo lo que rodea a esa función auxiliar: las reglas de plural, las claves que faltan, mantener cada archivo de idioma sincronizado con el código y, sobre todo, generar cada traducción desde cero. Las bibliotecas de código abierto de General Translation se encargan de la parte de ese trabajo que ocurre en tiempo de ejecución, y General Translation genera y actualiza las traducciones a partir de tu código.

## Cuándo basta con una i18n hecha a mano

* **Sin dependencias de terceros.** El diccionario y la función auxiliar son tuyos, y controlas cada línea de código.
* **La plataforma se encarga del formato.** `Intl.NumberFormat`, `Intl.DateTimeFormat`, `Intl.PluralRules` e `Intl.Locale` vienen [integrados en los navegadores modernos y en Node.js](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) y dan formato a monedas, fechas y categorías de plural según la configuración regional.
* **Textos breves y estables.** Para un prototipo, una herramienta interna o un sitio con un solo idioma adicional que redacta alguien del equipo, no hace falta más.
* **Idiomas que forman el plural como el inglés.** Tanto el inglés como el alemán usan solo [`one` y `other`](https://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html).

## Qué deja de funcionar a medida que crece

Esta es una primera versión típica, a la que se ha añadido un diccionario de polaco:

```js title="i18n.mjs"
const messages = {
  en: {
    greeting: 'Hello, {name}!',
    files: { one: '{count} file', other: '{count} files' },
    checkout: 'Checkout',
  },
  pl: {
    greeting: 'Cześć, {name}!',
    files: { one: '{count} plik', other: '{count} pliki' },
    // «checkout» aún no se ha traducido
  },
};

export function t(locale, key, vars = {}) {
  let message = messages[locale][key];
  if (typeof message === 'object') {
    message = vars.count === 1 ? message.one : message.other;
  }
  return message.replace(/\{(\w+)\}/g, (_, name) => vars[name]);
}

console.log(t('pl', 'greeting', { name: 'Ania' }));
console.log([1, 2, 5].map((count) => t('pl', 'files', { count })).join(', '));
console.log(t('pl', 'checkout'));
```

Al ejecutarlo con Node.js 24:

```text title="Output"
Cześć, Ania!
1 plik, 2 pliki, 5 pliki
TypeError: Cannot read properties of undefined (reading 'replace')
```

Aparecen dos errores a la vez. &quot;5 pliki&quot; es incorrecto (en polaco se dice &quot;5 plików&quot;), y la clave `checkout` sin traducir hace que falle el renderizado. La plataforma ofrece lo necesario para corregir ambos:

```js title="intl.mjs"
// Categorías de plural por idioma
for (const locale of ['en', 'ja', 'pl', 'ar']) {
  console.log(locale, new Intl.PluralRules(locale).resolvedOptions().pluralCategories.join(' '));
}
const pl = new Intl.PluralRules('pl');
console.log([1, 2, 5, 22].map((n) => `${n} → ${pl.select(n)}`).join(', '));

// Monedas y fechas
const date = new Date(Date.UTC(2026, 9, 16));
for (const locale of ['en-US', 'de-DE', 'ja-JP']) {
  const price = new Intl.NumberFormat(locale, { style: 'currency', currency: 'EUR' }).format(1234.5);
  const day = new Intl.DateTimeFormat(locale, { dateStyle: 'long', timeZone: 'UTC' }).format(date);
  console.log(locale, price, day);
}

// Dirección del texto
console.log(new Intl.Locale('ar').getTextInfo().direction);
```

```text title="Output"
en one other
ja other
pl one few many other
ar zero one two few many other
1 → one, 2 → few, 5 → many, 22 → few
en-US €1,234.50 October 16, 2026
de-DE 1.234,50 € 16. Oktober 2026
ja-JP €1,234.50 2026年10月16日
rtl
```

Cada corrección es pequeña, pero en conjunto suman:

* **Plurales.** `n === 1` falla en polaco (cuatro categorías) y en árabe (seis), por lo que la función auxiliar necesita [`Intl.PluralRules`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules), y cada diccionario necesita una cadena por categoría. (Consulta [¿Cómo manejo los plurales en React?](/kb/how-to-handle-plurals-in-react))
* **Orden de las palabras.** Los marcadores de posición como `{name}` permiten que cada idioma coloque el valor donde corresponda. La concatenación no: `t('by') + ' ' + author` pone el nombre al final, pero en japonés se escribe «Ana 著».
* **Formato.** `{count}` inserta el número tal cual, así que la función auxiliar también necesita [`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) para mostrar 12,500 como «12 500» en polaco.
* **Claves faltantes.** La función auxiliar necesita una cadena de alternativas de respaldo (idioma de destino, luego el de origen y, por último, la clave); de lo contrario, los usuarios verán `undefined` o un error.
* **Mantener los archivos sincronizados.** Nada te avisa de que a `pl` le falta `checkout` o de que conserva la redacción del mes pasado hasta que un usuario lo ve.
* **Idiomas de derecha a izquierda.** El árabe y el hebreo necesitan `lang` y `dir="rtl"` en la página, además de un diseño en espejo.
* **Motores de búsqueda.** Un selector que guarda la elección en el estado o en una cookie deja todos los idiomas en una sola URL, mientras que Google recomienda una URL por idioma ([Managing multilingual sites](https://developers.google.com/search/docs/specialty/international/managing-multi-regional-sites)). (Consulta [¿Cómo configuro el SEO para una aplicación de Next.js multilingüe?](/kb/multilingual-nextjs-seo))
* **Las traducciones.** Ninguna función auxiliar elimina este costo: alguien tiene que escribir «plików» y todas las demás cadenas en cada idioma, y volver a hacerlo cada vez que cambia el texto en inglés.

Cuando la función auxiliar ya gestiona las categorías de plural, las alternativas de respaldo y el formato de números, en la práctica has escrito el núcleo de una biblioteca de i18n, y aún te faltan las traducciones.

## Qué hace General Translation en su lugar

General Translation conserva lo que funciona del enfoque artesanal (textos legibles y el formato de la plataforma) y se encarga de las partes que van creciendo. Con `gt-react` (o `gt-next` para Next.js), el texto se queda en el componente dentro de [`<T>`](/docs/react/reference/components/t), así que no hay ningún diccionario ni función auxiliar que mantener:

```tsx title="Inbox.tsx"
import { T, Plural, Num, Var } from 'gt-react';

export function Inbox({ name, count }: { name: string; count: number }) {
  return (
    <T>
      <h1>Welcome back, <Var>{name}</Var></h1>
      <Plural
        n={count}
        singular={<p>You have <Num>{count}</Num> unread message.</p>}
        plural={<p>You have <Num>{count}</Num> unread messages.</p>}
      />
    </T>
  );
}
```

[`<Plural>`](/docs/react/reference/components/plural) elige una rama según las reglas de plural de CLDR de cada configuración regional, las mismas en las que se basa `Intl.PluralRules`, así que no hay ningún `n === 1` con el que equivocarse. [`<Num>`](/docs/react/reference/components/num) da formato a la cantidad según la configuración regional del lector, y el valor de [`<Var>`](/docs/react/reference/components/var) nunca se envía a la API de General Translation. Este es el componente renderizado en el servidor con `gt-react` 11.4.12, con una traducción al español añadida a mano en la plantilla de [`gt generate`](/docs/cli/reference/commands/generate) a modo de ejemplo (sin los separadores de texto de React):

```html title="Output"
<!-- en, count = 12500 -->
<h1>Welcome back, Ana</h1><p>You have 12,500 unread messages.</p>
<!-- es, count = 12500 -->
<h1>Hola de nuevo, Ana</h1><p>Tienes 12.500 mensajes sin leer.</p>
```

Cuando una configuración regional no tiene traducción para un bloque, [`<T>`](/docs/react/reference/components/t) renderiza el contenido de origen, no `undefined` ni un error.

El cambio más importante es que General Translation se encarga de generar las traducciones:

* **Generadas con contexto.** [`npx gt translate`](/docs/cli/reference/commands/translate) envía cada bloque [`<T>`](/docs/react/reference/components/t) junto con sus elementos, variables, ramas de plural y cualquier nota de [`context`](/docs/react/reference/components/t#context), y escribe un archivo por configuración regional. Un glosario fija la terminología y los prompts personalizados definen el tono en todos los proyectos que comparten un grupo de contexto. (Consulta [Definir el contexto para las traducciones](/docs/platform/dashboard/guides/defining-context-for-translations)).
* **Siempre sincronizadas.** Cada ejecución traduce el contenido nuevo y modificado, y reutiliza las traducciones existentes para el resto. Ejecútalo en CI o deja que [Locadex](/docs/platform/locadex/quickstart), el agente de IA de General Translation, abra pull requests según los disparadores que elijas. En aplicaciones Next.js y React, Locadex también puede envolver el texto existente en [`<T>`](/docs/react/reference/components/t).
* **Revisadas por personas.** Tu equipo edita las traducciones en el panel de control. (Consulta [Revisar y editar traducciones](/docs/platform/dashboard/guides/reviewing-translations)).
* **Dirección y enrutamiento.** [`useLocaleDirection`](/docs/react/reference/hooks/use-locale-direction) devuelve `'rtl'` para el árabe, y `gt-next` puede servir cada configuración regional en su propia URL mediante su [middleware](/docs/react/nextjs/app-router-middleware).

Las bibliotecas de JavaScript tienen licencia MIT y funcionan sin una cuenta de General Translation si proporcionas tú mismo las traducciones. Una aplicación configurada para cargar todas las traducciones desde su paquete no realiza ninguna llamada a General Translation en tiempo de ejecución. Para generar traducciones, usa el servicio alojado, con [precios basados en el uso](https://generaltranslation.com/pricing).

En el otro extremo, Profound publica su plataforma y su documentación en más de 47 configuraciones regionales con General Translation. (Consulta [despliegues en producción](https://generaltranslation.com/enterprise)).

## Implementación propia vs. una biblioteca vs. General Translation de un vistazo

|                              | Diccionario y función auxiliar propios                      | Biblioteca de código abierto, como i18next                                                                | General Translation                                                                                                                                                               |
| ---------------------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Dependencias                 | Ninguna                                                     | La biblioteca más los bindings del framework, como `react-i18next`                                        | `gt-react` o `gt-next`, más la CLI de `gt`                                                                                                                                        |
| Plurales                     | Tu propio código de selección, y cada forma en cada archivo | Selección con CLDR; las formas las aportan personas o un servicio de traducción conectado                 | [`<Plural>`](/docs/react/reference/components/plural) selecciona con reglas de CLDR; la traducción genera las formas de cada idioma de destino a partir de las ramas que escribes |
| Números, fechas, monedas     | APIs de `Intl` que llamas tú mismo                          | Formateadores integrados sobre `Intl`                                                                     | [`<Num>`](/docs/react/reference/components/num), [`<Currency>`](/docs/react/reference/components/currency) y [`<DateTime>`](/docs/react/reference/components/datetime)            |
| Traducciones faltantes       | Lo que haga tu función auxiliar                             | [Recurre a un idioma configurado y, si no, muestra la clave](https://www.i18next.com/principles/fallback) | Renderiza el contenido de origen                                                                                                                                                  |
| Sincronización entre idiomas | A mano o con tu propio script                               | Herramientas de extracción y un servicio de traducción que conectas                                       | Cada ejecución de [`npx gt translate`](/docs/cli/reference/commands/translate) traduce el contenido nuevo y modificado                                                            |
| Quién traduce                | Personas o un servicio que integras                         | Personas o un servicio de traducción conectado                                                            | IA con contexto de JSX marcado, glosario y prompts personalizados; tu equipo revisa en el panel de control                                                                        |
| Costo                        | Tu tiempo y los servicios que integres                      | Biblioteca gratuita; la traducción va aparte                                                              | Bibliotecas de JavaScript gratuitas; [traducción con pago por uso](https://generaltranslation.com/pricing)                                                                        |

## Cuándo implementarlo por tu cuenta

Implementarlo por tu cuenta tiene sentido cuando ofreces uno o dos idiomas, los textos son pocos y estables, tus idiomas pluralizan como el inglés y un compañero de equipo se encarga de las traducciones, o cuando se trata de un prototipo. Recurre a una biblioteca de código abierto como i18next cuando necesites reglas de plural y alternativas de respaldo y ya cuentes con traductores o con un sistema de gestión de traducciones. Usa General Translation cuando vayas a añadir varios idiomas, los textos cambien en cada lanzamiento o nadie del equipo deba ponerse a escribir formas plurales en polaco: General Translation genera las traducciones teniendo en cuenta el contexto de tu código y mantiene todos los idiomas al día con cada compilación. (Consulta [General Translation frente a i18next, react-intl y next-intl](/kb/general-translation-vs-i18n-libraries)).

## Conserva tu diccionario y deja que la CLI lo traduzca

No hace falta reescribir tu función auxiliar para dejar de traducir a mano. Mueve los mensajes de cada idioma a un archivo JSON (`locales/en.json`, `locales/es.json`), conserva tu `t()` y haz que `gt.config.json` apunte a ellos con el marcador de posición `[locale]`:

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

[`npx gt translate --dry-run`](/docs/cli/reference/commands/translate) muestra `locales/en.json` como origen, y una ejecución completa genera `locales/es.json`. Este ejemplo usa mensajes en inglés y en español con la misma estructura de claves y marcadores de posición sencillos como `{name}`. Un archivo complementario `locales/en.metadata.json` permite añadir contexto o límites de caracteres por clave. Consulta [JSON](/docs/cli/reference/formats/json-files) y [Metadatos asociados a claves](/docs/cli/reference/keyed-metadata). Tu función auxiliar sigue encargándose de la búsqueda de claves y de la selección de plurales; comprueba ambas en la salida renderizada en español.

Para dejar de usar la función auxiliar, envuelve los componentes en [`<T>`](/docs/react/reference/components/t) de uno en uno, o conserva las claves con [`useTranslations`](/docs/react/guides/translating-with-dictionaries). Si el trabajo lo hace un agente de programación, proporciónale las [instrucciones para agentes](/docs/overview/for-coding-agents) de General Translation en lugar de pedirle una función auxiliar `t()`. Empieza con el [Inicio rápido de Next.js](/docs/react/nextjs-quickstart) o con la [Guía de inicio rápido para una SPA de React](/docs/react/react-spa-quickstart).

## Conclusiones clave

* Un diccionario, una función auxiliar `t()` y las API integradas de `Intl` bastan si tienes uno o dos idiomas, poco texto y plurales que funcionan como en inglés.
* A medida que la aplicación crece, te toca mantener la selección de plurales, las alternativas de respaldo, el formato, la sincronización de archivos, la compatibilidad con right-to-left, las URL por configuración regional y el proceso que genera las traducciones.
* Las bibliotecas de General Translation se encargan del trabajo en tiempo de ejecución, General Translation genera las traducciones usando tu código como contexto y la CLI puede traducir un diccionario JSON hecho a mano si decides conservarlo.

## 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.
- [¿Cómo gestiono los plurales en React?](https://generaltranslation.com/es/kb/how-to-handle-plurals-in-react.mdx): No codifiques la lógica de pluralización a mano con comprobaciones como n === 1. Para aplicaciones solo en inglés basta con una pequeña función auxiliar, pero las aplicaciones multilingües necesitan reglas de pluralización adaptadas a la configuración regional, y un componente de i18n como `<Plural>` de gt-react o gt-next se encarga de ellas en todos los idiomas.
- [¿Cómo configuro el SEO de una aplicación de Next.js multilingüe?](https://generaltranslation.com/es/kb/multilingual-nextjs-seo.mdx): Asigna a cada idioma su propia URL, define el atributo lang de html, haz que la URL canónica de cada página apunte a sí misma, añade versiones alternativas hreflang para cada idioma, traduce los títulos y las descripciones, e incluye todas las versiones de idioma en tu sitemap.
- [¿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.
- [Alternativas a Google Translate: General Translation vs. Google Translate](https://generaltranslation.com/es/kb/general-translation-vs-google-translate.mdx): Google Translate es una forma rápida de traducir textos puntuales, pero lanzar un producto en otro idioma también exige traducir cada cadena en su contexto, mantener una terminología coherente, gestionar correctamente las variables y los plurales, revisar las traducciones y contar con un proceso de lanzamiento. General Translation entiende el contexto de cada cadena en tu código y automatiza todo el flujo de trabajo de localización, desde el código hasta la revisión y cada lanzamiento.

## Previous and next questions

- Previous question: [¿Cuál es la mejor biblioteca de i18n para una aplicación React?](https://generaltranslation.com/es/kb/best-react-i18n-library.mdx)
- Next question: [¿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)

## Sitemap

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