Comenzando con la Internacionalización (i18n) usando Intlayer, Lynx y React
¿Qué es Intlayer?
Intlayer es una librería de internacionalización (i18n) de código abierto e innovadora que simplifica el soporte multilingüe en aplicaciones modernas. Funciona en muchos entornos JavaScript/TypeScript, incluido Lynx (mediante el paquete react-intlayer).
Con Intlayer, puedes:
- Gestionar fácilmente las traducciones usando diccionarios declarativos a nivel de componente.
- Tener soporte con TypeScript gracias a la generación automática de tipos.
- Localizar contenido de forma dinámica, incluyendo cadenas de la interfaz de usuario (y en React para web, también metadatos en HTML, etc.).
- Aprovechar funciones avanzadas, como la detección y conmutación dinámica de local.
Paso 1: Instala las dependencias
Desde tu proyecto Lynx, instala los siguientes paquetes:
npm install intlayer react-intlayer lynx-intlayer
Paquetes
intlayer
Herramienta principal de i18n para la configuración, contenido de diccionarios, generación de tipos y comandos CLI.react-intlayer
Integración con React que provee los contextos y hooks de React que usarás en Lynx para obtener y cambiar el local.lynx-intlayer
Integración con Lynx que provee el plugin para usar Intlayer con el bundler de Lynx.
Paso 2: Crea un archivo de configuración de Intlayer
En la raíz de tu proyecto (o en algún lugar conveniente), crea un archivo de configuración Intlayer. Por ejemplo:
import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = { internationalization: { locales: [ Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH, // ... Agrega cualquier otro local que necesites ], defaultLocale: Locales.ENGLISH, },};export default config;
En esta configuración puedes:
- Definir tu lista de locales soportados.
- Fijar un local por defecto.
- Más adelante, podrías añadir opciones avanzadas (p. ej., logs, directorios de contenido personalizados, etc.).
- Consulta la documentación de configuración de Intlayer para más información.
Paso 3: Agrega el plugin de Intlayer al bundler de Lynx
Para usar Intlayer en Lynx, debes añadir el plugin en tu archivo lynx.config.ts:
import { defineConfig } from "@lynx-js/rspeedy";import { pluginIntlayerLynx } from "lynx-intlayer/plugin";export default defineConfig({ plugins: [ // ... otros plugins pluginIntlayerLynx(), ],});
Paso 4: Agrega el proveedor de Intlayer
Para mantener sincronizado el idioma del usuario en toda tu aplicación, debes envolver tu componente raíz con IntlayerProvider de react-intlayer.
Además, necesitas invocar la función intlayerPolyfill para asegurar que Intlayer funcione correctamente en Lynx.
import { root } from "@lynx-js/react";import { App } from "./App.js";import { IntlayerProvider } from "react-intlayer";import { intlayerPolyfill } from "lynx-intlayer";intlayerPolyfill();root.render( <IntlayerProvider> <App /> </IntlayerProvider>);if (import.meta.webpackHot) { import.meta.webpackHot.accept();}
Paso 5: Declara tu contenido
Crea archivos de declaración de contenido en cualquier lugar de tu proyecto (generalmente dentro de src/), usando cualquiera de las extensiones que soporta Intlayer:
- .content.ts
- .content.mjs
- .content.cjs
- .content.json
- etc.
Ejemplo (TypeScript con nodos TSX para Lynx):
import { t, type Dictionary } from "intlayer";const appContent = { key: "app", content: { title: "React", subtitle: t({ en: "on Lynx", fr: "sur Lynx", es: "en Lynx", }), description: t({ en: "Tap the logo and have fun!", fr: "Appuyez sur le logo et amusez-vous!", es: "¡Toca el logo y diviértete!", }), hint: [ t({ en: "Edit", fr: "Modifier", es: "Editar", }), " src/App.tsx ", t({ en: "to see updates!", fr: "pour voir les mises à jour!", es: "para ver actualizaciones!", }), ], },} satisfies Dictionary;export default appContent;
Para más información sobre la declaración de contenido, visita la documentación de contenido de Intlayer.
Paso 4 (corregido en numeración): Usa Intlayer en tus componentes
Utiliza el hook useIntlayer en los componentes hijos para obtener contenido localizado:
import { useCallback, useState } from "@lynx-js/react";import { useIntlayer } from "react-intlayer";import "./App.css";import arrow from "./assets/arrow.png";import lynxLogo from "./assets/lynx-logo.png";import reactLynxLogo from "./assets/react-logo.png";import { LocaleSwitcher } from "./components/LocaleSwitcher.jsx";export const App = () => { const [alterLogo, setAlterLogo] = useState(false); const { title, subtitle, description, hint } = useIntlayer("app"); const onTap = useCallback(() => { "background only"; setAlterLogo(!alterLogo); }, [alterLogo]); return ( <view> <view className="Background" /> <view className="App"> <view className="Banner"> <view className="Logo" bindtap={onTap}> {alterLogo ? ( <image src={reactLynxLogo} className="Logo--react" /> ) : ( <image src={lynxLogo} className="Logo--lynx" /> )} </view> <text className="Title">{title}</text> <text className="Subtitle">{subtitle}</text> </view> <view className="Content"> <image src={arrow} className="Arrow" /> <text className="Description">{description}</text> <text className="Hint"> {hint[0]} <text style={{ fontStyle: "italic" }}>{hint[1]}</text> {hint[2]} </text> </view> <LocaleSwitcher /> <view style={{ flex: 1 }}></view> </view> </view> );};
Cuando utilices content.someKey en props basados en cadenas (por ejemplo, el title de un botón o los children de un componente Text), usa content.someKey.value para obtener la cadena real.
(Opcional) Paso 5 (corregido en numeración): Cambiar el local de la aplicación
Para conmutar entre locales desde tus componentes, puedes usar el método setLocale del hook useLocale:
import { type FC } from "react";import { getLocaleName } from "intlayer";import { useLocale } from "react-intlayer";export const LocaleSwitcher: FC = () => { const { setLocale, availableLocales, locale } = useLocale(); return ( <view style={{ display: "flex", flexDirection: "row", justifyContent: "center", alignItems: "center", gap: 10, }} > {availableLocales.map((localeEl) => ( <text key={localeEl} style={{ color: localeEl === locale ? "#fff" : "#888", fontSize: "12px", }} bindtap={() => setLocale(localeEl)} > {getLocaleName(localeEl)} </text> ))} </view> );};
Esto provoca que se vuelvan a renderizar todos los componentes que usan contenido de Intlayer, mostrándose ahora las traducciones para el nuevo local.
Consulta la documentación de useLocale para más detalles.
Configurar TypeScript (si usas TypeScript)
Intlayer genera definiciones de tipo en una carpeta oculta (por defecto .intlayer) para mejorar la autocompletación y detectar errores de traducción:
// tsconfig.json{ // ... tu configuración existente de TS "include": [ "src", // tu código fuente ".intlayer", // <-- asegura incluir los tipos generados automáticamente // ... cualquier otra carpeta que incluyas ],}
Esto habilita características como:
- Autocompletado para las claves de tu diccionario.
- Comprobación de tipos que advierte si accedes a una clave inexistente o si hay discrepancias de tipo.
Configuración de Git
Para evitar subir a tu repositorio los archivos generados automáticamente por Intlayer, añade lo siguiente a tu .gitignore:
# Ignora los archivos generados por Intlayer.intlayer
Para profundizar
- Editor visual: Usa el Intlayer Visual Editor para administrar traducciones de forma visual.
- Integración con CMS: También puedes externalizar y obtener el contenido de tus diccionarios desde un CMS.
- Comandos CLI: Explora el CLI de Intlayer para tareas como extraer traducciones o comprobar claves faltantes.
Si tienes una idea para mejorar esta documentación, no dudes en contribuir enviando una pull request en GitHub.
Enlace de GitHub a la documentación