Traducir los textos de una aplicación web puede parecer tan simple como crear un archivo JSON con todas las traducciones, pero a medida que el proyecto crece, esa solución inicial se convierte en un problema de rendimiento y mantenimiento. Aquí se explora paso a paso cómo estructurar la internacionalización de labels en React y Next.js, desde lo más básico hasta una arquitectura escalable que aprovecha Context y hooks.
¿Por qué un solo archivo JSON no es suficiente para internacionalizar?
El punto de partida más sencillo es un único archivo JSON que contenga todas las traducciones organizadas por secciones de locale. Por ejemplo, una sección es para español y otra en-US para inglés, cada una con pares de llave-valor [0:42]. Dentro de un componente de React, bastaría con importar ese JSON, cargarlo desde el servidor con getServerSideProps de Next.js y acceder a la llave correspondiente.
Esta solución funciona, pero presenta tres desventajas claras:
- Entre más locales se agreguen, más pesado se vuelve el archivo.
- Entre más labels existan, mayor será la carga innecesaria para cada página.
- La responsabilidad de importar y leer el archivo se repite en cada componente.
¿Cómo dividir los archivos de traducción de forma eficiente?
La primera mejora consiste en crear un archivo JSON por cada locale [2:07]. En lugar de un solo archivo gigante, se tendría es.json y en-US.json por separado. Pero se puede ir más allá: dividir también por componente.
Dentro de una carpeta locales/es/, cada componente tendría su propio archivo, por ejemplo checkout.json, con únicamente los labels que ese componente necesita [2:30]. Lo mismo aplicaría para locales/en-US/. Si una página usa veinte labels y otra solo uno, no tiene sentido cargar todos para ambas.
¿Es un problema tener labels duplicados entre componentes?
Cuando se divide por componente, es inevitable que algunos labels se repitan. Sin embargo, esto no siempre es negativo. La internacionalización va mucho más allá de traducir texto; también involucra decisiones culturales y de copy [3:16]. Un equipo de editores podría decidir que en una página la palabra adecuada sea "interesado" y en otra "conócenos", aunque ambas correspondan al mismo concepto de contact us. Por eso, en aplicaciones grandes con equipos de editores, tener llaves duplicadas no causa daño y otorga flexibilidad editorial.
¿Cómo usar React Context y hooks para escalar la internacionalización?
React Context permite compartir datos a través de todos los componentes sin pasar propiedades manualmente de padre a hijo [4:12]. Esto es ideal para abstraer toda la lógica de internacionalización en un único lugar: fácil de leer, fácil de mantener y fácil de eliminar si se necesita cambiar de estrategia.
Con un hook personalizado llamado useTranslations, el componente ya no importa ningún JSON directamente. El hook se conecta al contexto, determina qué locale está activo y devuelve los labels listos para usar [4:44].
jsx
import { useTranslations } from './hooks/useTranslations';
function Checkout() {
const labels = useTranslations();
return <button>{labels.comprar}</button>;
}
El componente no necesita saber qué locale está cargado. No hace if/else ni lógica condicional. Solo usa la llave correspondiente donde la necesita.
¿Cómo se construye el hook useTranslations?
Primero se crea un contexto con useContext de React [5:20]. Dentro de ese contexto se almacenan dos cosas:
- Los archivos de traducción disponibles.
- El valor del locale activo en ese momento.
Next.js provee mecanismos basados en el routing para determinar el locale activo, lo cual se puede conectar directamente al contexto. Una vez identificado el locale, el hook obtiene los labels correspondientes y los retorna al componente.
Los hooks son una herramienta ideal para extraer y compartir lógica entre componentes, evitando la repetición de código y centralizando las decisiones de internacionalización.
¿Conviene usar librerías como react-i18next o hacerlo desde cero?
Existen librerías muy populares como React Internationalization y react-i18next que resuelven exactamente este problema [5:58]. Si se examina su funcionamiento interno, están basadas en los mismos principios: Context, hooks y archivos divididos por locale.
El reto propuesto es doble [6:15]:
- Implementarlo desde cero con Context, hooks y Next.js para dominar la mecánica completa.
- Probar alguna librería como
react-i18next-next y analizar sus ventajas y desventajas.
Ninguna librería es mágica. Cada una sacrifica algo o resuelve ciertos problemas mejor que otras. La decisión final debe basarse en las necesidades específicas del sitio y en un análisis informado de las consecuencias de cada enfoque.
¿Ya has implementado internacionalización en tus proyectos? Comparte tu experiencia y qué estrategia te ha funcionado mejor.