React Internationalization (i18n) con react-i18next y Intlayer
Resumen
- Intlayer te ayuda a gestionar traducciones a través de archivos de declaración de contenido a nivel de componente.
- react-i18next es una integración popular de React para i18next que proporciona hooks como useTranslation para obtener cadenas localizadas en tus componentes.
Cuando se combinan, Intlayer puede exportar diccionarios en JSON compatible con i18next, de modo que react-i18next pueda consumirlos en tiempo de ejecución.
¿Por Qué Usar Intlayer con react-i18next?
Los archivos de declaración de contenido Intlayer ofrecen una mejor experiencia para desarrolladores porque son:
Flexibles en la Ubicación de Archivos
Coloca cada archivo de declaración de contenido justo al lado del componente que lo necesita. Esta estructura te permite mantener las traducciones co-localizadas, evitando traducciones huérfanas cuando los componentes se mueven o se eliminan.bash.└── src └── components └── MyComponent ├── index.content.ts # Archivo de declaración de contenido └── index.tsx
Traducciones Centralizadas
Un solo archivo de declaración de contenido recopila todas las traducciones necesarias para un componente, haciendo que las traducciones faltantes sean más fáciles de detectar.
Con TypeScript, incluso obtienes errores en tiempo de compilación si faltan traducciones.
Instalación
En un proyecto de Create React App, instala estas dependencias:
# Con npmnpm install intlayer react-i18next i18next i18next-resources-to-backend
# Con yarnyarn add intlayer react-i18next i18next i18next-resources-to-backend
# Con pnpmpnpm add intlayer react-i18next i18next i18next-resources-to-backend
¿Qué Son Estos Paquetes?
- intlayer – La CLI y biblioteca central para gestionar configuraciones de i18n, declaraciones de contenido y construir salidas de diccionario.
- react-intlayer – Integración específica de React para Intlayer, proporcionando notablemente algunos scripts para automatizar la construcción de diccionarios.
- react-i18next – Biblioteca de integración específica de React para i18next, incluyendo el hook useTranslation.
- i18next – El marco subyacente para el manejo de traducciones.
- i18next-resources-to-backend – Un backend de i18next que importa dinámicamente recursos JSON.
Configurando Intlayer para Exportar Diccionarios de i18next
Crea (o actualiza) tu intlayer.config.ts en la raíz de tu proyecto:
import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = { internationalization: { // Agrega tantos locales como desees locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], defaultLocale: Locales.ENGLISH, }, content: { // Indica a Intlayer que cree JSON compatible con i18next dictionaryOutput: ["i18next"], // Elige un directorio de salida para los recursos generados // Esta carpeta se creará si no existe. i18nextResourcesDir: "./i18next/resources", },};export default config;
Nota: Si no estás usando TypeScript, puedes crear este archivo de configuración como .cjs, .mjs o .js (consulta la documentación de Intlayer para más detalles).
Construyendo los Recursos de i18next
Una vez que tus declaraciones de contenido estén en su lugar (sección siguiente), ejecuta el comando de construcción de Intlayer:
# Con npmnpx run intlayer build
# Con yarnyarn intlayer build
# Con pnpmpnpm intlayer build
Esto generará tus recursos de i18next dentro del directorio ./i18next/resources por defecto.
Una salida típica podría verse así:
.└── i18next └── resources ├── en │ └── my-content.json ├── fr │ └── my-content.json └── es └── my-content.json
Donde cada clave de declaración de Intlayer se utiliza como un espacio de nombres de i18next (por ejemplo, my-content.json).
Importando Diccionarios en tu Configuración de react-i18next
Para cargar dinámicamente estos recursos en tiempo de ejecución, utiliza i18next-resources-to-backend. Por ejemplo, crea un archivo i18n.ts (o .js) en tu proyecto:
import i18next from "i18next";import { initReactI18next } from "react-i18next";import resourcesToBackend from "i18next-resources-to-backend";i18next // plugin react-i18next .use(initReactI18next) // carga dinámicamente los recursos .use( resourcesToBackend((language: string, namespace: string) => { // Ajusta la ruta de importación a tu directorio de recursos return import(`../i18next/resources/${language}/${namespace}.json`); }) ) // Inicializa i18next .init({ // Localidad de respaldo fallbackLng: "en", // Puedes agregar otras opciones de configuración de i18next aquí, consulta: // https://www.i18next.com/overview/configuration-options });export default i18next;
import i18next from "i18next";import { initReactI18next } from "react-i18next";import resourcesToBackend from "i18next-resources-to-backend";i18next .use(initReactI18next) .use( resourcesToBackend( (language, namespace) => import(`../i18next/resources/${language}/${namespace}.json`) ) ) .init({ fallbackLng: "en", });export default i18next;
Luego, en tu archivo raíz o índice (por ejemplo, src/index.tsx), importa esta configuración de i18n antes de renderizar la App:
import React from "react";import ReactDOM from "react-dom/client";// Inicializa i18n antes de cualquier otra cosaimport "./i18n";import App from "./App";ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( <React.StrictMode> <App /> </React.StrictMode>);
Creando y Gestionando Tus Declaraciones de Contenido
Intlayer extrae traducciones de "archivos de declaración de contenido" ubicados en cualquier lugar debajo de ./src (por defecto).
Aquí hay un ejemplo mínimo en TypeScript:
import { t, type Dictionary } from "intlayer";const content = { // La "clave" será tu espacio de nombres de i18next (por ejemplo, "my-component") key: "my-component", content: { // Cada llamada "t" es un nodo de traducción separado heading: t({ en: "Hello World", fr: "Bonjour le monde", es: "Hola Mundo", }), description: t({ en: "My i18n description text...", fr: "Ma description en i18n...", es: "Mi descripción en i18n...", }), },} satisfies Dictionary;export default content;
Si prefieres JSON, .cjs o .mjs, consulta la documentación de Intlayer.
Por defecto, las declaraciones de contenido válidas coinciden con el patrón de extensión de archivo:
*.content.{ts,tsx,js,jsx,mjs,cjs,json}
Usando las Traducciones en Componentes de React
Después de que hayas construido tus recursos de Intlayer y configurado react-i18next, puedes usar directamente el hook useTranslation de react-i18next.
Por ejemplo:
import { FC } from "react";import { useTranslation } from "react-i18next";/** * El "espacio de nombres" de i18next es la `clave` de Intlayer de "MyComponent.content.ts" * así que pasaremos "my-component" a useTranslation(). */const MyComponent: FC = () => { const { t } = useTranslation("my-component"); return ( <div> <h1>{t("heading")}</h1> <p>{t("description")}</p> </div> );};export default MyComponent;
Ten en cuenta que la función t hace referencia a claves dentro de tu JSON generado. Para una entrada de contenido de Intlayer llamada heading, usarás t("heading").
Opcional: Integrarse con Scripts de Create React App (CRACO)
react-intlayer proporciona un enfoque basado en CRACO para construcciones personalizadas y configuración del servidor de desarrollo. Si deseas que el paso de construcción de Intlayer se integre sin problemas, puedes:
- Instalar react-intlayer (si no lo has hecho): bash npm install react-intlayer --save-dev
Ajustar tus scripts de package.json para usar los scripts de react-intlayer:
jsonc"scripts": { "start": "react-intlayer start", "build": "react-intlayer build", "transpile": "intlayer build"}
Los scripts de react-intlayer se basan en CRACO. También puedes implementar tu propia configuración basada en el plugin craco de intlayer. Consulta un ejemplo aquí.
Ahora, al ejecutar npm run build, yarn build, o pnpm build se activan las construcciones de Intlayer y CRA.
Configuración de TypeScript
Intlayer proporciona definiciones de tipo autogeneradas para tu contenido. Para asegurarte de que TypeScript las reconozca, agrega types (o types si lo configuraste de otro modo) a tu arreglo include de tsconfig.json:
{ "compilerOptions": { // ... }, "include": ["src", "types"],}
Esto permitirá que TypeScript infiera la estructura de tus traducciones para una mejor autocompletación y detección de errores.
Configuración de Git
Se recomienda ignorar archivos y carpetas generados automáticamente por Intlayer. Agrega esta línea a tu .gitignore:
# Ignorar los archivos generados por Intlayer.intlayeri18next
Por lo general, no debes comprometer estos recursos o artefactos internos de construcción .intlayer, ya que pueden regenerarse en cada construcción.
Si tienes una idea para mejorar esta blogumentación, no dudes en contribuir enviando una pull request en GitHub.
Enlace de GitHub al blog