# General Translation Knowledge Base: ¿Cómo debo nombrar las claves de traducción de i18n?
URL: https://generaltranslation.com/es/kb/i18n-key-naming.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Nombra las claves según dónde aparece el texto y qué significa, como checkout.summary.title, y no según su redacción en inglés. Asigna a cada uso distinto su propia clave, aunque el texto en inglés coincida: en alemán, el botón Open se traduce como Öffnen y el estado Open como Offen.
Category: Internacionalización
Last updated: 2026-10-20
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-20

Una clave es el identificador que usa tu código para buscar una traducción, como en `t('summary.title', { ns: 'checkout' })`. Un buen nombre resiste los cambios de redacción, indica a los traductores dónde aparece el texto y permite localizar fácilmente las claves que ya no se usan. Las siguientes convenciones se aplican a i18next, react-i18next, Rails I18n, vue-i18n y a cualquier otra biblioteca que lea JSON o YAML basados en claves; los ejemplos usan la sintaxis de i18next y se probaron con i18next 26.5.3.

## 1. Organiza en espacios de nombres por funcionalidad o pantalla

Empieza cada clave con el área del producto a la que pertenece, seguida del componente y, por último, del elemento.

* ✅ `checkout.summary.title`, `settings.billing.cancelButton`
* ❌ `title1`, `text_47`, `newString`

Cuando el primer segmento es un archivo independiente, se trata de un espacio de nombres y no de parte de la ruta de la clave. Si `summary.title` está almacenada en `checkout.json`, i18next la encuentra con `t('summary.title', { ns: 'checkout' })` o `t('checkout:summary.title')`. En cambio, `t('checkout.summary.title')` devuelve la propia cadena de la clave, porque busca un objeto `checkout` en el espacio de nombres predeterminado.

El prefijo le indica al traductor dónde aparece el texto y te permite dividir los catálogos en archivos. i18next llama a estos archivos [espacios de nombres](https://www.i18next.com/principles/namespaces) y recomienda dividirlos por vista, por funcionalidad o por módulo de carga diferida, además de crear un espacio de nombres `common` para etiquetas como Guardar y Cancelar. En React, react-i18next carga uno con `useTranslation('checkout')`, y la [opción `keyPrefix`](https://react.i18next.com/latest/usetranslation-hook) permite acortar las rutas profundas.

## 2. Describe el significado, no la redacción

Una clave debería seguir siendo válida aunque el equipo de marketing reescriba la frase.

* ✅ `auth.login.submit`
* ❌ `auth.login.clickHereToSignInNow`

Si más adelante el botón dice «Continuar», la primera clave seguirá siendo precisa. La segunda, en cambio, describirá un texto que ya no existe y, tarde o temprano, alguien la renombrará, lo que romperá todas las referencias y dejará huérfanas las traducciones.

## 3. Una clave por contexto, no una por cadena en inglés

Dos cadenas que se escriben igual en inglés suelen traducirse de forma distinta. &quot;Open&quot; en un botón es un verbo; &quot;Open&quot; como estado de un ticket es un adjetivo. En alemán se usa *Öffnen* para el primero y *Offen* para el segundo.

* ✅ `files.actions.open` y `tickets.status.open`
* ❌ un único `common.open` reutilizado para ambos casos

Reserva el espacio de nombres compartido `common` para etiquetas cuyo significado sea idéntico en todas partes, como el botón Cancelar. Los sistemas basados en el texto de origen resuelven este mismo problema mediante el contexto: [`msgctxt`](https://www.gnu.org/software/gettext/manual/html_node/Contexts.html) de GNU gettext permite que una misma cadena en inglés tenga dos traducciones.

## 4. Elige JSON anidado o plano, y no los mezcles

Dentro de `checkout.json`, i18next interpreta `summary.title` como una ruta, porque su `keySeparator` tiene `.` como valor predeterminado. Ambos formatos funcionan; elige uno para que todos los archivos, revisores y herramientas sigan el mismo criterio.

```json title="locales/en/checkout.json (nested)"
{
  "summary": {
    "title": "Order summary",
    "taxNotice": "Tax is calculated at checkout."
  }
}
```

```json title="locales/en/checkout.json (flat)"
{
  "summary.title": "Order summary",
  "summary.taxNotice": "Tax is calculated at checkout."
}
```

Para archivos planos, la [documentación de configuración](https://www.i18next.com/overview/configuration-options) de i18next recomienda establecer `keySeparator` en `false`. Elige también una convención de uso de mayúsculas y minúsculas (segmentos en `camelCase` o `snake_case`) y aplícala en todos los archivos.

## 5. Usa los sufijos de plural y de contexto de tu biblioteca

i18next selecciona las formas plurales mediante sufijos y requiere que la variable se llame `count`. Una entrada `_zero` reemplaza la regla del idioma cuando el valor de `count` es 0, y los ordinales añaden `_ordinal`:

```json title="locales/en/checkout.json"
{
  "cart": {
    "itemCount_zero": "Your cart is empty",
    "itemCount_one": "{{count}} item",
    "itemCount_other": "{{count}} items"
  }
}
```

`t('cart.itemCount', { count: 0 })` devuelve &quot;Your cart is empty&quot;; con 1 devuelve &quot;1 item&quot;, y con 5, &quot;5 items&quot;. Un idioma con más categorías de plural añade claves como `itemCount_few` e `itemCount_many`. (Consulta la [documentación de plurales de i18next](https://www.i18next.com/translation-function/plurals) y [¿Qué es el formato de mensajes ICU?](/kb/icu-message-format) para conocer las categorías de cada idioma).

* ✅ `itemCount_one`, `itemCount_other` y, para texto con género, claves de [contexto](https://www.i18next.com/translation-function/context) como `friend_male` y `friend_female`
* ❌ sufijos inventados como `itemCount_singular` e `itemCount_plural`, que la biblioteca no seleccionará

Las bibliotecas basadas en el formato de mensajes ICU (react-intl, next-intl, Lingui), en cambio, agrupan todas las formas plurales en un único mensaje bajo una sola clave.

## 6. Nunca construyas una oración a partir de varias claves

El orden de las palabras varía de un idioma a otro, así que una oración repartida entre varias claves no se puede traducir correctamente.

* ❌ `t('account.hello') + name + t('account.welcomeBack')`
* ✅ una sola clave con un marcador de posición: `"account.welcome": "Hello, {{name}}! Welcome back."`

Si un mensaje incluye una cantidad, mantén también la oración completa en cada forma plural, con los sufijos de la convención 5.

El [manual de GNU gettext](https://www.gnu.org/software/gettext/manual/html_node/Preparing-Strings.html) establece la misma regla para sus catálogos: traduce oraciones completas y usa cadenas de formato en lugar de concatenarlas.

## 7. Elige entre claves estables y el texto de origen como clave

No todos los sistemas inventan nombres. La cuestión es a quién le corresponde el identificador:

| Enfoque                                           | Ejemplo                                  | Ventaja                                                                            | Costo                                                                                                                    |
| ------------------------------------------------- | ---------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| Claves semánticas (i18next, Rails I18n)           | `t('summary.title', { ns: 'checkout' })` | Los cambios en los textos no afectan al código; las claves documentan la ubicación | Alguien tiene que nombrar, organizar y depurar cada clave                                                                |
| Texto de origen como clave (gettext)              | `_("Order summary")`                     | El código sigue siendo legible; no hace falta nombrar nada                         | Cualquier cambio en el texto en inglés crea una nueva entrada; los conflictos entre textos idénticos requieren `msgctxt` |
| IDs generados a partir de texto inline (FormatJS) | `defaultMessage="Order summary"`         | El mensaje está junto a su uso; los IDs se generan automáticamente                 | Requiere un plugin de compilación y un paso de extracción                                                                |

Usa claves semánticas cuando los textos se gestionan fuera de la base de código (por ejemplo, si un equipo de contenido edita las cadenas en un TMS) o cuando las aplicaciones web y móviles comparten un mismo catálogo. Usa el texto de origen o mensajes inline cuando son los desarrolladores quienes escriben los textos y quieres que la revisión de código muestre las palabras que ven los usuarios.

## 8. Mantén las claves fuera de las URL, la analítica y la lógica

Las claves y las cadenas traducidas son solo para mostrar. No envíes `t('checkout:cta')` como nombre de un evento de analítica (cada configuración regional registraría un evento distinto), no construyas el slug de una ruta a partir de una clave y no bifurques la lógica con `label === t('status.open')`. Usa un nombre de evento fijo, un slug que controles y un enum o código de estado. Así, renombrar una clave o editar una traducción no podrá romper un panel de control, un enlace ni una condición.

## 9. Limpia automáticamente las claves sin usar y las que faltan

Los catálogos se desincronizan con el tiempo: las claves siguen ahí después de eliminar su componente y las claves nuevas se publican sin traducir. Ejecuta un verificador en CI.

* **i18next**: [`i18next-cli`](https://github.com/i18next/i18next-cli) sustituye al obsoleto `i18next-parser`. En un pequeño proyecto de prueba, `npx i18next-cli status --unused` detectó una clave huérfana, `oldPromoBanner`, sin modificar ningún archivo; después, `npx i18next-cli extract` la eliminó (su opción `removeUnusedKeys` tiene `true` como valor predeterminado) y escribió entradas vacías en alemán para todas las claves, incluidas `itemCount_one` e `itemCount_other`. `npx i18next-cli status` termina con un error mientras falten traducciones, y `rename-key` cambia el nombre de una clave en los archivos de origen y de configuración regional. El análisis estático no puede detectar las claves que se construyen en tiempo de ejecución, como ``t(`status.${code}`)``, así que `extract` las considera no utilizadas y las elimina. Indica esos prefijos en la opción `preservePatterns` (por ejemplo, `'status.*'`) o escribe cada clave de forma explícita en el código.
* **Rails**: i18n-tasks detecta las claves que faltan y las que no se usan en tu código Ruby y ERB. (Consulta [General Translation vs. i18n-tasks](/kb/general-translation-vs-i18n-tasks)).

## Cómo gestiona General Translation las claves

Con el componente [`<T>`](/docs/react/reference/components/t) de `gt-react` o `gt-next`, el texto en inglés se queda en el propio componente y no hace falta ponerle nombre a ninguna clave:

```tsx title="CheckoutSummary.tsx"
import { T } from 'gt-react';

export function CheckoutSummary() {
  return (
    <T>
      <h2>Order summary</h2>
      <small>Tax is calculated at checkout.</small>
    </T>
  );
}
```

[`npx gt translate`](/docs/cli/reference/commands/translate) extrae el contenido que sigue presente en tu código de origen, así que, al eliminar un componente, ya no hace falta mantener sus claves a mano. Los distintos usos de &quot;Open&quot; siguen necesitando contexto: `<T context="Ticket status">Open</T>` o `gt('Open', { $context: 'Ticket status' })` con [`useGT`](/docs/react/reference/hooks/use-gt). La prop opcional [`id`](/docs/react/reference/components/t#id) de [`<T>`](/docs/react/reference/components/t), o la opción `$id` de la función de traducción, asigna a una entrada un identificador estable para el Editor de Traducciones. (Consulta [¿Puedo hacer i18n sin archivos de traducción?](/kb/i18n-without-translation-files)).

Los equipos que prefieran trabajar con claves pueden seguir usándolas. Escribe un único diccionario de origen, como `dictionary.json`, y léelo con [`useTranslations`](/docs/react/reference/hooks/use-translations). El mismo comando se encarga de traducirlo, y si buscas un id que no existe en el diccionario, se lanza un error en lugar de renderizar la clave sin procesar. (Consulta [Traducir con diccionarios](/docs/react/guides/translating-with-dictionaries)). Los archivos JSON existentes de i18next o next-intl se traducen tal cual, y un [archivo `.metadata.json`](/docs/cli/reference/keyed-metadata) complementario añade contexto o un límite de caracteres por clave: el equivalente con claves de la convención 3.

## Conclusiones clave

* Nombra las claves según su ubicación y significado (`checkout.summary.title`), nunca según su redacción o posición (`text_47`).
* Asigna claves distintas a «Open» como verbo y a «Open» como estado; comparte claves solo cuando el significado sea idéntico.
* Respeta al pie de la letra los sufijos de plural de la biblioteca: i18next usa `_one`, `_other` y `_zero`, mientras que las bibliotecas ICU agrupan los plurales en un único mensaje.
* Ejecuta `i18next-cli status --unused` o i18n-tasks en CI para que no se acumulen claves sin uso ni faltantes.
* El componente [`<T>`](/docs/react/reference/components/t) de General Translation no necesita claves, y su modo diccionario con [`useTranslations`](/docs/react/reference/hooks/use-translations) las mantiene para los equipos que prefieran usarlas.

## Related questions

- [¿Puedo hacer i18n sin archivos de traducción?](https://generaltranslation.com/es/kb/i18n-without-translation-files.mdx): Sí. Las bibliotecas gt-react y gt-next de General Translation permiten hacer i18n en React y Next.js sin claves de traducción y sin tener que mantener un archivo JSON por idioma. El texto permanece inline en JSX dentro del componente `<T>`, y el comando gt translate genera las traducciones de cada idioma durante la compilación, con contexto extraído de tu código. Locadex puede mantenerlas al día mediante pull requests.
- [General Translation vs. i18n-tasks: ¿cuál deberías usar?](https://generaltranslation.com/es/kb/general-translation-vs-i18n-tasks.mdx): i18n-tasks es una gema de Ruby que detecta claves de Rails I18n faltantes y sin usar, ordena los archivos de configuración regional y puede completar las claves faltantes mediante Google Translate, DeepL, OpenAI, Yandex o watsonx. General Translation traduce archivos de configuración regional completos con tu glosario, tus prompts personalizados y la revisión en el panel de control. Cumplen funciones distintas, y muchos equipos pueden usar ambas.
- [Alternativas a i18next: General Translation vs. i18next](https://generaltranslation.com/es/kb/general-translation-vs-i18next.mdx): Elige General Translation para mantener los textos inline en los componentes de React y generar traducciones a partir de su estructura JSX y del contexto del producto. También puedes seguir usando i18next y recurrir a General Translation para traducir los catálogos existentes. i18next se encarga de renderizar los mensajes y seleccionar los plurales, pero las traducciones las genera un servicio aparte.
- [¿Qué es el formato de mensajes ICU?](https://generaltranslation.com/es/kb/icu-message-format.mdx): El formato de mensajes ICU es una sintaxis que permite que una sola cadena traducible contenga variables, plurales, opciones de selección y ordinales, como {count, plural, one {# file} other {# files}}. Cada idioma conserva las categorías de plural de CLDR que necesita: el inglés usa one y other, mientras que el polaco añade few y many.
- [¿Cómo encuentro cadenas codificadas de forma fija que no están traducidas?](https://generaltranslation.com/es/kb/find-hardcoded-strings.mdx): Ejecuta en CI un linter que marque los literales de cadena visibles para el usuario, como la regla no-literal-string de eslint-plugin-i18next para JSX, la comprobación HardcodedText de Android Lint o el linter HardCodedString de erb_lint para Rails. Después, recorre la app con una pseudoconfiguración regional para detectar el texto que las comprobaciones estáticas no pueden rastrear.

## Previous and next questions

- Previous question: [Lista de comprobación de pruebas de localización para aplicaciones multilingües](https://generaltranslation.com/es/kb/multilingual-app-launch-checklist.mdx)
- Next question: [¿Cómo detecto el idioma del navegador de un usuario?](https://generaltranslation.com/es/kb/detect-user-language.mdx)

## Sitemap

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