Recientemente trabajé en un proyecto emocionante que implicaba crear un sitio web capaz de cambiar entre idiomas para atraer a una audiencia más amplia. Esto me hizo comprender mejor el concepto de “localización”, que generalmente implica adaptar el contenido para que sea relevante, accesible y fácilmente identificable para los usuarios en diferentes idiomas y regiones.
La localización no se trata solo de traducir palabras, se trata de crear una experiencia que haga que los usuarios se sientan como en casa, sin importar su idioma. Por ejemplo, plataformas globales como Amazon hacen que el cambio de idioma sea tan fluido que se siente casi mágico. Más allá de mejorar la experiencia del usuario, esta característica juega un papel crucial en impulsar negocios al llegar a una audiencia más amplia y fomentar conexiones más fuertes con los clientes en todo el mundo.
Tabla de Contenidos
¿Qué es i18n y por qué usarlo?
i18n, que significa internacionalización, significa que una aplicación admite múltiples idiomas. “i18n” se deriva del hecho de que hay 18 letras entre la primera “i” y la última “n” en “internacionalización”. Se trata de hacer que tu aplicación sea adaptable para audiencias globales mediante la traducción de texto, el formato de fechas y números, la gestión de monedas y el cumplimiento de convenciones regionales.
Al habilitar la internacionalización, tu aplicación se convierte no solo en una herramienta, sino en una plataforma inclusiva que se dirige directamente a las preferencias y la cultura del usuario.
¡Comencemos
Crearemos una aplicación web multilingüe de demostración muy simple con una función de cambio a modo oscuro para demostrar cómo lograr este concepto.
Requisitos previos
-
Conocimientos básicos de React: Debes entender cómo crear componentes, gestionar el estado y utilizar Hooks como
useState
yuseEffect
. Si eres nuevo en React, te recomiendo empezar con la documentación oficial de React para tener una base sólida. -
Familiaridad con los Conceptos de Internacionalización – Conocer los conceptos básicos de internacionalización (i18n) y por qué es importante te dará contexto para el proyecto. Las secciones anteriores de este artículo cubren lo esencial.
-
Tailwind CSS – Usaremos Tailwind CSS para el estilo. Es un marco de trabajo CSS de utilidad primero que te ayuda a construir diseños modernos y receptivos sin salir de tu HTML. Si no estás familiarizado, revisa la documentación de Tailwind.
-
Node.js – Asegúrate de que Node.js esté instalado en tu sistema para manejar las dependencias. Puedes descargar la última versión desde Node.js.
-
Gestor de paquetes: Se necesita npm (incluido con Node.js) o yarn para gestionar las dependencias del proyecto
Herramientas que utilizaremos
-
Editor de código
-
Biblioteca de localización: react-i18next
-
Biblioteca de iconos: hero-icons
Paso 1: Cómo configurar el proyecto
Inicializar el proyecto
Usar Vite para una configuración rápida:
npm create vite@latest multilingual-demo
Siga las instrucciones que aparecen en su terminal, seleccionando React y TypeScript para el desarrollo como se muestra en la imagen a continuación:
Instalar dependencias
Ejecute los siguientes comandos en su terminal para instalar las dependencias requeridas para este proyecto:
npm install i18next react-i18next i18next-browser-languagedetector i18next-http-backend heroicons
npm install tailwindcss postcss autoprefixer
npx tailwindcss init
Configurar TailwindCSS
Actualice el archivo tailwind.config.ts
:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{js,jsx,ts,tsx}"],
darkMode: "class", // Para nuestra funcionalidad de modo oscuro
theme: {
container: {
center: true,
padding: "1.25rem",
screens: {
sm: "1200px",
},
},
extend: {},
},
plugins: [],
};
Agregue TailwindCSS a src/index.css
:
@tailwind base;
@tailwind components;
@tailwind utilities;
Paso 2: Cómo configurar la internacionalización con i18next
Inicialice i18next
Cree un archivo i18n.tsx
en la carpeta src
y configure i18next:
import i18next from "i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import { initReactI18next } from "react-i18next";
import Backend from "i18next-http-backend";
i18next.use(LanguageDetector).use(initReactI18next).use(Backend).init({
returnObjects: true,
fallbackLng: "en", // Idioma al que se cambiará si el seleccionado no está configurado
debug: true, // Para permitirnos ver errores
// lng: "en", // Idioma predeterminado en inglés
});
Echemos un vistazo rápido al contenido de este archivo, ya que desempeña un papel clave en habilitar la funcionalidad de traducción. Este archivo es responsable de configurar el núcleo del proceso de traducción y asegurarse de que la función de cambio de idioma funcione sin problemas en su aplicación.
-
i18next
: La biblioteca de internacionalización central que estamos utilizando para la traducción. -
LanguageDetector
: Nos ayuda a detectar automáticamente el idioma preferido del usuario, basándose en la configuración del navegador. -
initReactI18next
: Es responsable de integrar el plugini18next
con React y proporciona Hooks como el HookuseTranslation
y otras utilidades. -
Backend
: Obtiene datos de traducción dinámicamente de una fuente externa. En este caso, utilizaremos archivos JSON.
Importa este archivo en el archivo main.tsx
:
//main.tsx
import React, { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.tsx";
import "./i18n.tsx"; //Importar aquí
createRoot(document.getElementById("root")!).render(
<StrictMode>
<React.Suspense fallback="loading">
<App />
</React.Suspense>
</StrictMode>
);
Crea Archivos de Traducción
En el directorio public/locales
, crea subcarpetas para cada idioma (por ejemplo, en
, fr
) e incluye archivos translation.json
:
en/translation.json
{
"greeting": "Welcome to the Language Playground",
"detail": {
"line1": "Did you know that over 7,000 languages are spoken worldwide?",
"line2": "This Playground demonstrates how web applications can support users in multiple languages, making them accessible and inclusive to people from different backgrounds."
}
}
fr/translation.json
{
"greeting": "Bienvenue sur le terrain de jeu linguistique",
"detail": {
"line1": "Saviez-vous que plus de 7 000 langues sont parlées dans le monde ?",
"line2": "Ce terrain de jeu démontre comment les applications web peuvent prendre en charge les utilisateurs dans plusieurs langues, les rendant accessibles et inclusives aux personnes de différents horizons."
}
}
Aquí, puedes agregar tantos idiomas con sus archivos de traducción que se suministrarán a i18next
. Ten en cuenta que las claves en los archivos JSON son las mismas que se usarían como referencias al mostrarlas en el sitio web.
Paso 3: Cómo Construir Componentes
Crea una carpeta components
en el directorio src
y agrega los siguientes componentes:
Selector de Idioma
Crea el componente LanguageSelector
– que contiene un elemento select
para ayudar a los usuarios a cambiar de idioma dinámicamente:
import { useEffect, useState } from "react";
import i18next from "i18next";
import { useTranslation } from "react-i18next";
type languageOption = { language: string; code: string };
const languageOptions: languageOption[] = [
{
language: "English",
code: "en",
},
{ language: "French", code: "fr" },
{ language: "German", code: "de" },
{ language: "Spanish", code: "es" },
{ language: "Arabic", code: "ar" },
{ language: "Yoruba", code: "yo" },
];
const LanguageSelector = () => {
// Establecer el idioma inicial detectado por i18next o el idioma predeterminado
const [language, setLanguage] = useState(i18next.language);
const { i18n } = useTranslation();
const handleLanguageChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const selectedLanguage = e.target.value;
setLanguage(selectedLanguage);
i18next.changeLanguage(selectedLanguage); // Actualizar el idioma en i18next
};
useEffect(() => {
document.body.dir = i18n.dir(); // Establecer el cuerpo en ltr o rtl
}, [i18n, i18n.language]);
return (
<select
id="language"
value={language}
onChange={handleLanguageChange}
className="p-2 border border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring focus:ring-indigo-200 focus:ring-opacity-50
dark:bg-gray-800 dark:border-gray-600 dark:text-gray-200 dark:focus:border-indigo-400 dark:focus:ring-indigo-700 dark:focus:ring-opacity-50"
>
{languageOptions.map(({ language, code }, key) => (
<option value={code} key={key}>
{language}
</option>
))}
</select>
);
};
export default LanguageSelector;
-
Inicializa el idioma con el idioma detectado por
i18next
o el idioma establecido por defecto. -
El Hook
useTranslation
expone la instanciai18n
dei18next
para interactuar con la configuración de internacionalización. -
La función
handleLanguageChange
se utilizaría para actualizar el idioma seleccionado por el usuario. Se activa cuando el usuario selecciona un nuevo idioma en el menú desplegable.
Implementando la Dirección del Texto
El atributo dir
en HTML es una característica crítica para garantizar la accesibilidad y la inclusividad en las aplicaciones web, especialmente al tratar con idiomas que difieren en la dirección del texto. Por ejemplo:
-
Izquierda a Derecha (LTR): La mayoría de los idiomas, incluyendo inglés, francés y español, siguen esta dirección.
Derecha a Izquierda (RTL): Idiomas como árabe y hebreo requieren que el alineamiento del texto y el diseño se inviertan para mantener la legibilidad y el contexto cultural.
Para lograr esto en nuestra aplicación, establecemos el document.body.dir
al dir
de i18n
mientras escuchamos los cambios en la selección del idioma usando el gancho useEffect
Alternar Modo Oscuro
Crea el componente DarkModeToggle
para cambiar entre el modo claro y oscuro según lo prefiera el usuario.
import { useEffect, useState } from "react";
import { SunIcon, MoonIcon } from "@heroicons/react/solid";
const DarkModeToggle = () => {
const [darkMode, setDarkMode] = useState(false);
useEffect(() => {
// Comprobar almacenamiento local o preferencia del sistema en la primera carga
const isDark =
localStorage.getItem("theme") === "dark" ||
(!localStorage.getItem("theme") &&
window.matchMedia("(prefers-color-scheme: dark)").matches);
setDarkMode(isDark);
document.documentElement.classList.toggle("dark", isDark);
}, []);
const toggleDarkMode = () => {
setDarkMode(!darkMode);
document.documentElement.classList.toggle("dark", !darkMode);
localStorage.setItem("theme", !darkMode ? "dark" : "light");
};
return (
<button
aria-label="Toggle dark mode"
onClick={toggleDarkMode}
className="p-1 rounded"
>
{darkMode ? (
<SunIcon
className="w-6 h-6 text-yellow-500 "
onClick={toggleDarkMode}
/>
) : (
<MoonIcon className="w-6 h-6 text-gray-900 " onClick={toggleDarkMode} />
)}
</button>
);
};
export default DarkModeToggle;
Componente de Encabezado
El componente Header
sirve como un componente padre para los componentes DarkModeToggle
y languageSelector
.
import DarkModeToggle from "./DarkModeToggle";
import LanguageSelector from "./LanguageSelector";
const Header = () => {
return (
<header className="container flex justify-between">
<DarkModeToggle />
<LanguageSelector />
</header>
);
};
export default Header;
Paso 4: Componente Principal de la Aplicación
En el archivo src/app
, incluye lo siguiente:
import { useTranslation } from "react-i18next";
import Header from "./components/Header";
const App = () => {
const { t } = useTranslation();
const line1 = t("detail.line1");
const line2 = t("detail.line2");
return (
<div className="h-[100vh] bg-white text-black dark:bg-gray-900 dark:text-white py-8">
<Header />
<div className="container text-center max-w-2xl mt-28">
<h1 className="text-4xl font-bold">{t("greeting")}</h1>
<p className="mt-8">{line1}</p>
<p className="mt-2">{line2}</p>
</div>
</div>
);
};
export default App;
-
El Hook
useTranslation
dereact-i18next
expone la funciónt
, que se utiliza para recuperar texto traducido. -
Recupera la cadena traducida basada en una clave de sus archivos de traducción (por ejemplo,
en.json
,fr.json
).
Al seguir estos pasos, su aplicación debería estar completamente funcional con traducciones integradas de manera transparente. Así es como se ve el resultado final de nuestra aplicación:
Consulte la demostración en vivo y el código fuente en GitHub
Conclusión
Crear sitios web que permitan a los usuarios seleccionar su idioma preferido no es solo un logro técnico, sino un paso hacia hacer que la web sea más inclusiva y acogedora.
Al combinar la internacionalización (i18n) con herramientas como React-i18next y el estilo con Tailwind CSS, puede construir aplicaciones que sean flexibles, fáciles de usar y accesibles para una audiencia global.
En este proyecto, recorrimos la configuración de i18n, agregamos un selector de idioma e incluimos el “modo oscuro” para una mejor usabilidad.
Referencias
Source:
https://www.freecodecamp.org/news/build-multilingual-apps-with-i18n-in-react/