Traducir tu app React es esencial para llegar a una audiencia global. i18next es uno de los frameworks de internacionalización más populares y potentes para React, proporcionando una solución robusta para gestionar traducciones. Esta guía te guiará a través del proceso de traducir una app React usando i18next.
Entendiendo la Localización de React con i18next
i18next es un framework de internacionalización que funciona perfectamente con React a través del paquete react-i18next. Soporta múltiples idiomas, pluralización, interpolación y muchas otras características necesarias para localización profesional.
Paso 1: Instalar Dependencias
Primero, instala los paquetes necesarios:
npm install i18next react-i18next i18next-browser-languagedetector
O con yarn:
yarn add i18next react-i18next i18next-browser-languagedetector
Paso 2: Crear Archivos de Traducción
Crea un directorio locales en tu carpeta src y agrega archivos de traducción para cada idioma:
src/locales/en/translation.json (Inglés - por defecto):
{
"welcome": "Welcome to our app!",
"button": {
"submit": "Submit",
"cancel": "Cancel",
"delete": "Delete"
},
"error": {
"network": "Network error. Please try again.",
"notFound": "Page not found"
},
"itemsCount": "{{count}} items",
"itemsCount_one": "{{count}} item",
"itemsCount_zero": "No items",
"userGreeting": "Hello, {{name}}! You have {{count}} messages.",
"userGreeting_one": "Hello, {{name}}! You have {{count}} message.",
"userGreeting_zero": "Hello, {{name}}! You have no messages."
}
src/locales/es/translation.json (Español):
{
"welcome": "¡Bienvenido a nuestra aplicación!",
"button": {
"submit": "Enviar",
"cancel": "Cancelar",
"delete": "Eliminar"
},
"error": {
"network": "Error de red. Por favor, inténtalo de nuevo.",
"notFound": "Página no encontrada"
},
"itemsCount": "{{count}} elementos",
"itemsCount_one": "{{count}} elemento",
"itemsCount_zero": "No hay elementos",
"userGreeting": "¡Hola, {{name}}! Tienes {{count}} mensajes.",
"userGreeting_one": "¡Hola, {{name}}! Tienes {{count}} mensaje.",
"userGreeting_zero": "¡Hola, {{name}}! No tienes mensajes."
}
src/locales/fr/translation.json (Francés):
{
"welcome": "Bienvenue dans notre application!",
"button": {
"submit": "Soumettre",
"cancel": "Annuler",
"delete": "Supprimer"
},
"error": {
"network": "Erreur réseau. Veuillez réessayer.",
"notFound": "Page non trouvée"
},
"itemsCount": "{{count}} éléments",
"itemsCount_one": "{{count}} élément",
"itemsCount_zero": "Aucun élément",
"userGreeting": "Bonjour, {{name}}! Vous avez {{count}} messages.",
"userGreeting_one": "Bonjour, {{name}}! Vous avez {{count}} message.",
"userGreeting_zero": "Bonjour, {{name}}! Vous n'avez aucun message."
}
Paso 3: Configurar i18next
Crea un archivo de configuración i18n:
src/i18n.js:
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import translationEN from './locales/en/translation.json';
import translationES from './locales/es/translation.json';
import translationFR from './locales/fr/translation.json';
const resources = {
en: {
translation: translationEN
},
es: {
translation: translationES
},
fr: {
translation: translationFR
}
};
i18n
.use(LanguageDetector) // Detecta el idioma del usuario
.use(initReactI18next) // Pasa i18n a react-i18next
.init({
resources,
fallbackLng: 'en', // Idioma por defecto
debug: false, // Establecer a true para depuración
interpolation: {
escapeValue: false // React ya escapa valores
},
react: {
useSuspense: false // Establecer a true si usas Suspense
}
});
export default i18n;
O con TypeScript (src/i18n.ts):
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import translationEN from './locales/en/translation.json';
import translationES from './locales/es/translation.json';
import translationFR from './locales/fr/translation.json';
const resources = {
en: {
translation: translationEN
},
es: {
translation: translationES
},
fr: {
translation: translationFR
}
} as const;
i18n
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources,
fallbackLng: 'en',
debug: false,
interpolation: {
escapeValue: false
},
react: {
useSuspense: false
}
});
export default i18n;
Paso 4: Inicializar i18n en tu App
Importa i18n en tu componente App principal:
src/App.js:
import React from 'react';
import './i18n'; // Importar configuración i18n
import HomePage from './components/HomePage';
function App() {
return (
<div className="App">
<HomePage />
</div>
);
}
export default App;
O con TypeScript (src/App.tsx):
import React from 'react';
import './i18n';
import HomePage from './components/HomePage';
const App: React.FC = () => {
return (
<div className="App">
<HomePage />
</div>
);
};
export default App;
Paso 5: Usar Traducciones en Componentes
Usa el hook useTranslation para acceder a las traducciones:
Antes:
function Welcome() {
return <h1>Welcome to our app!</h1>;
}
Después:
import { useTranslation } from 'react-i18next';
function Welcome() {
const { t } = useTranslation();
return <h1>{t('welcome')}</h1>;
}
Con TypeScript:
import { useTranslation } from 'react-i18next';
const Welcome: React.FC = () => {
const { t } = useTranslation();
return <h1>{t('welcome')}</h1>;
};
Paso 6: Manejar Claves de Traducción Anidadas
Accede a claves anidadas usando notación de punto:
import { useTranslation } from 'react-i18next';
function Buttons() {
const { t } = useTranslation();
return (
<div>
<button>{t('button.submit')}</button>
<button>{t('button.cancel')}</button>
<button>{t('button.delete')}</button>
</div>
);
}
Paso 7: Interpolación de Cadenas con Variables
Pasa variables a las traducciones:
translation.json:
{
"userGreeting": "Hello, {{name}}! You have {{count}} messages."
}
Componente:
import { useTranslation } from 'react-i18next';
function UserGreeting({ name, messageCount }) {
const { t } = useTranslation();
return (
<p>
{t('userGreeting', {
name: name,
count: messageCount
})}
</p>
);
}
// Uso: <UserGreeting name="John" messageCount={5} />
// Inglés: "Hello, John! You have 5 messages."
// Español: "¡Hola, John! Tienes 5 mensajes."
Paso 8: Pluralización
i18next maneja la pluralización automáticamente basándose en el conteo:
translation.json:
{
"itemsCount": "{{count}} items",
"itemsCount_one": "{{count}} item",
"itemsCount_zero": "No items"
}
Componente:
import { useTranslation } from 'react-i18next';
function ItemCount({ count }) {
const { t } = useTranslation();
return <p>{t('itemsCount', { count })}</p>;
}
// Ejemplos de uso:
// <ItemCount count={0} /> → "No items" (Inglés) / "No hay elementos" (Español)
// <ItemCount count={1} /> → "1 item" (Inglés) / "1 elemento" (Español)
// <ItemCount count={5} /> → "5 items" (Inglés) / "5 elementos" (Español)
Paso 9: Formatear Fechas y Números
Usa las características de formateo de i18next o la API Intl de JavaScript:
Fechas:
import { useTranslation } from 'react-i18next';
function DateDisplay({ date }) {
const { t, i18n } = useTranslation();
const formattedDate = new Intl.DateTimeFormat(i18n.language, {
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long'
}).format(date);
return <p>{formattedDate}</p>;
}
// Inglés: "Wednesday, March 20, 2025"
// Español: "miércoles, 20 de marzo de 2025"
Números:
import { useTranslation } from 'react-i18next';
function NumberDisplay({ number }) {
const { i18n } = useTranslation();
const formattedNumber = new Intl.NumberFormat(i18n.language).format(number);
return <p>{formattedNumber}</p>;
}
// Inglés: "1,234.56"
// Español: "1.234,56"
Moneda:
import { useTranslation } from 'react-i18next';
function CurrencyDisplay({ amount }) {
const { i18n } = useTranslation();
const formattedCurrency = new Intl.NumberFormat(i18n.language, {
style: 'currency',
currency: 'USD'
}).format(amount);
return <p>{formattedCurrency}</p>;
}
// Inglés (US): "$1,234.56"
// Español (ES): "1.234,56 €"
Paso 10: Cambiar Idioma Programáticamente
Permite a los usuarios cambiar idiomas:
import { useTranslation } from 'react-i18next';
function LanguageSwitcher() {
const { i18n } = useTranslation();
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
};
return (
<div>
<button onClick={() => changeLanguage('en')}>English</button>
<button onClick={() => changeLanguage('es')}>Español</button>
<button onClick={() => changeLanguage('fr')}>Français</button>
</div>
);
}
Con detección de idioma:
function LanguageSwitcher() {
const { i18n } = useTranslation();
const currentLanguage = i18n.language;
return (
<select
value={currentLanguage}
onChange={(e) => i18n.changeLanguage(e.target.value)}
>
<option value="en">English</option>
<option value="es">Español</option>
<option value="fr">Français</option>
</select>
);
}
Paso 11: Manejar Idiomas de Derecha a Izquierda (RTL)
Para idiomas RTL como árabe y hebreo:
import { useTranslation } from 'react-i18next';
import { useEffect } from 'react';
function App() {
const { i18n } = useTranslation();
useEffect(() => {
const isRTL = ['ar', 'he', 'fa'].includes(i18n.language);
document.documentElement.dir = isRTL ? 'rtl' : 'ltr';
document.documentElement.lang = i18n.language;
}, [i18n.language]);
return (
<div className="App">
{/* Contenido de tu app */}
</div>
);
}
CSS para soporte RTL:
/* Usa propiedades lógicas */
.container {
padding-inline-start: 1rem;
padding-inline-end: 1rem;
margin-inline-start: auto;
margin-inline-end: auto;
}
/* O usa variables CSS */
:root[dir="rtl"] {
--text-align: right;
}
:root[dir="ltr"] {
--text-align: left;
}
Mejores Prácticas
1. Usar Claves de Traducción Descriptivas
Malo:
{
"msg1": "Submit"
}
Bueno:
{
"button": {
"submit": "Submit"
}
}
2. Organizar Traducciones por Característica
translation.json:
{
"auth": {
"login": "Login",
"logout": "Logout",
"signup": "Sign Up"
},
"dashboard": {
"title": "Dashboard",
"welcome": "Welcome back!"
},
"settings": {
"title": "Settings",
"language": "Language"
}
}
3. Proporcionar Contexto en las Claves de Traducción
Usa claves descriptivas que indiquen contexto:
{
"button": {
"delete": "Delete"
},
"action": {
"deleteItem": "Delete Item",
"deleteAccount": "Delete Account"
}
}
4. Usar Namespaces para Apps Grandes
Para aplicaciones grandes, divide las traducciones en namespaces:
i18n.js:
import commonEN from './locales/en/common.json';
import authEN from './locales/en/auth.json';
import dashboardEN from './locales/en/dashboard.json';
const resources = {
en: {
common: commonEN,
auth: authEN,
dashboard: dashboardEN
},
// ... otros idiomas
};
Uso:
const { t } = useTranslation('auth');
return <h1>{t('login')}</h1>;
5. Manejar Traducciones Faltantes
Configura el comportamiento de fallback:
i18n.init({
fallbackLng: 'en',
saveMissing: true, // Registra claves faltantes
missingKeyHandler: (lng, ns, key) => {
console.warn(`Traducción faltante: ${key} para idioma: ${lng}`);
}
});
6. Probar Longitudes de Cadenas
Algunos idiomas son más largos que otros. Diseña tu UI para acomodar:
- Alemán y finlandés: 30-50% más largo que inglés
- Idiomas asiáticos: Pueden necesitar más espacio vertical
Errores Comunes
1. Olvidar Importar i18n
Siempre importa la configuración i18n en tu componente App principal:
import './i18n'; // ¡No olvides esto!
2. No Usar el Hook useTranslation
Malo:
import i18n from './i18n';
return <p>{i18n.t('welcome')}</p>; // Funciona pero no es reactivo
Bueno:
const { t } = useTranslation();
return <p>{t('welcome')}</p>; // Reactivo a cambios de idioma
3. Codificar Cadenas de Formato Directamente
Malo:
const price = `$${amount.toFixed(2)}`;
Bueno:
const { i18n } = useTranslation();
const price = new Intl.NumberFormat(i18n.language, {
style: 'currency',
currency: 'USD'
}).format(amount);
4. No Probar Todos los Idiomas
Siempre prueba tu app en todos los idiomas soportados para detectar:
- Traducciones faltantes
- Problemas de diseño de UI
- Desbordamiento de texto
- Problemas de diseño RTL
Avanzado: Carga Perezosa de Traducciones
Para mejor rendimiento, carga traducciones bajo demanda:
i18n.js:
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend'; // Instalar: npm install i18next-http-backend
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
fallbackLng: 'en',
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json'
}
});
Avanzado: Soporte TypeScript
Para mejor soporte TypeScript, crea definiciones de tipo:
src/types/i18next.d.ts:
import 'react-i18next';
import translationEN from '../locales/en/translation.json';
declare module 'react-i18next' {
interface CustomTypeOptions {
defaultNS: 'translation';
resources: {
translation: typeof translationEN;
};
}
}
Avanzado: Persistir Preferencia de Idioma
Guarda la elección de idioma del usuario en localStorage:
import { useTranslation } from 'react-i18next';
import { useEffect } from 'react';
function App() {
const { i18n } = useTranslation();
useEffect(() => {
const savedLanguage = localStorage.getItem('language');
if (savedLanguage) {
i18n.changeLanguage(savedLanguage);
}
}, [i18n]);
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
localStorage.setItem('language', lng);
};
// ... resto del componente
}
Usar con Next.js
Para aplicaciones Next.js, usa next-i18next:
npm install next-i18next
next-i18next.config.js:
module.exports = {
i18n: {
defaultLocale: 'en',
locales: ['en', 'es', 'fr'],
},
};
next.config.js:
const { i18n } = require('./next-i18next.config');
module.exports = {
i18n,
};
Conclusión
Localizar tu app React con i18next es sencillo cuando sigues estos pasos:
- Instalar paquetes
i18nextyreact-i18next - Crear archivos JSON de traducción para cada idioma
- Configurar i18next con detección de idioma
- Importar configuración i18n en tu componente App
- Usar hook
useTranslationen todos tus componentes - Manejar pluralización e interpolación de cadenas
- Formatear fechas y números usando API Intl
- Permitir a los usuarios cambiar idiomas
- Probar exhaustivamente en todos los idiomas soportados
Siguiendo estas prácticas, crearás una app que proporciona una experiencia nativa para usuarios en todo el mundo, expandiendo significativamente tu base de usuarios potencial.
Optimiza tu Flujo de Trabajo de Localización React
Gestionar traducciones para múltiples idiomas puede volverse complejo a medida que tu app crece. Considera usar una plataforma de gestión de traducciones para:
- Colaborar con traductores
- Mantener traducciones sincronizadas con tu código base
- Automatizar el flujo de trabajo de traducción
- Mantener consistencia en todos los idiomas
- Generar archivos de traducción automáticamente
¿Listo para llevar tu app React a nivel global? Explora la plataforma de localización de AZbox y optimiza tu flujo de trabajo de traducción: