Estás haciendo mal el i18n en Next.js
La internacionalización en JavaScript se ha asentado en una convención defectuosa: extraer cada cadena de cara al usuario a un archivo JSON, asignarle una clave y hacer referencia a esa clave en tus componentes. t('home.hero.title') en lugar del texto en sí. Tu interfaz vive en un sitio; tu contenido, en otro.
Esto funciona. Miles de aplicaciones se lanzan así. Pero no ofrece una buena experiencia de desarrollo.
Leer t('checkout.summary.total') en una revisión de código no te dice nada: tienes que abrir un archivo JSON para ver qué cambió. Las claves hay que inventarlas, organizarlas en espacios de nombres y mantenerlas sincronizadas. Las traducciones obsoletas se acumulan porque nadie sabe qué claves siguen en uso. El problema está tan extendido que existen categorías enteras de herramientas solo para gestionarlo: extensiones de IDE que sugieren claves automáticamente, generadores de tipos que las validan y linters que marcan las que no se usan. Estas herramientas están resolviendo un problema creado por un paradigma mal diseñado.
El componente <T>
El contenido no debe separarse de donde se usa. Un componente que renderiza un encabezado, un párrafo y un botón debe ser la única fuente de verdad sobre lo que muestran esos elementos, no un intermediario que apunta a cadenas almacenadas en otro lugar. Cuando tu código y tus traducciones son dos sistemas paralelos, acaban desincronizándose. Inevitablemente.
¿Y si la biblioteca funcionara al revés: adaptándose a tu código en lugar de pedirte que lo reestructures? Así es como debería ser la i18n.
import { T } from 'gt-next';
function Hero() {
return (
<T>
<h1>Ship your product worldwide</h1>
<p>Reach every market without rewriting your app.</p>
</T>
);
}Envuelve tu JSX en <T>. El texto en inglés se queda justo donde lo escribiste. Cuando un usuario accede en español o japonés, el contenido dentro de <T> se traduce: estructura, formato y todo.
Sin claves. Sin archivos JSON. Sin referencias cruzadas. Tu código es la fuente de verdad.
Configuración
La sintaxis anterior proviene de gt-next, una biblioteca de i18n de código abierto para el App Router de Next.js. Para empezar, solo necesitas ejecutar un comando:
npx gt@latest initEl asistente de configuración instala dependencias, envuelve tu configuración de Next.js con withGTConfig, agrega GTProvider a tu layout raíz, crea un gt.config.json con tus configuraciones regionales, configura las claves de API de desarrollo para la recarga en caliente de las traducciones y configura el almacenamiento de traducciones en la CDN, todo de forma interactiva.
Una vez hecho esto, envuelve el contenido en <T>, ejecuta tu servidor de desarrollo y usa el componente <LocaleSelector> para cambiar entre idiomas:
import { LocaleSelector } from 'gt-next';
function Header() {
return (
<header>
<nav>{/* ... */}</nav>
<LocaleSelector />
</header>
);
}Las traducciones se realizan on-demand durante el desarrollo para que puedas ver tu aplicación en cualquier idioma de inmediato.
Despliegue
En producción, las traducciones se generan con antelación.
-
Obtén una clave de API de producción en dash.generaltranslation.com. Las claves de producción empiezan por
gtx-api-(a diferencia de las clavesgtx-dev-que se usan localmente). -
Añade el paso
translatea tu proceso de compilación:
{
"scripts": {
"build": "npx gt translate --publish && next build"
}
}El comando translate analiza tu base de código para detectar todos los usos de <T>, genera las traducciones y las publica en una CDN. Cuando se compila tu aplicación, todas las configuraciones regionales están listas.
Próximos pasos
- Componentes de variable — maneja contenido dinámico dentro de
<T>con<Var>,<Num>y<Currency> - Componentes de branching — renderiza contenido de forma condicional según la configuración regional con
<Plural>y<Branch> useGTygetGT— traduce cadenas simples para atributos, placeholders y metadatos- Modo autónomo — usa gt-next sin la plataforma de General Translation