React. Añadiendo traducciones con i18next
La librería i18next probablemente sea la mejor opción disponible para añadir traducciones a una web desarrollada con React
English version: https://medium.com/@ger86/react-adding-translations-with-i18next-b6bf52cd621e
En este artículo quiero contaros los elementos básicos de la librería i18next, la cual tiene una integración muy sencilla con la librería ReactJS lo cual nos va a permitir añadir traducciones a nuestros textos de una forma muy muy sencilla. Además cuenta con sus propios hooks algo que viene a ser un añadido ahora que los componentes funcionales son la tendencia en el desarrollo con esta librería.
Además esta misma librería la podemos emplear tanto con React como con React Native, lo cual supone una tremenda ventaja pues podremos reciclar la lógica asociada a ella si nos vemos obligados a desarrollar para plataformas web y móviles.
Y sí, aunque no lo veremos en este artículo, i18next es 100% compatible con server side rendering y frameworks como NextJS.
Así que sin entretenernos más, ¡vamos a ver las principales características que nos ofrece!
🧰 Instalación y configuración
Lo primero que haremos será instalar i18next mediante npm / yarn:
yarn add react-i18next
A continuación será necesario configurar la librería para poder emplearla dentro de nuestros componentes. Esto es recomendable hacerlo en un archivo aparte (por aquello de separar la lógica) que importaremos en el archivo index.js
de nuestro proyecto.
En mi caso yo suelo crear este archivo de configuración dentro de la carpeta config
como podéis ver en la línea 4 de la siguiente pieza de código:

La configuración inicial de la librería puede ser tan sencilla como la que veis a continuación:

Importaremos la librería i18next
y la configuraremos del siguiente modo:
- Por medio del método
use
configuraremos el plugin que permite conectar la librería con React. - En el método
init
especificaremos por medio de un objeto las traducciones de nuestra aplicación, quedando éstas agrupadas por idioma. En nuestro caso tenemos disponibles dos idiomas:en
yes
y una traducción a la que accederemos por medio del identificador/clavetitle
. - Además, en el método
init
también estableceremos el idioma actual así como el idioma por defecto que se usará cuando una traducción no esté disponible en el idioma seleccionado.
Con esto ya tendremos configurada la librería y lista para funcionar como veremos a continuación.
Empleando el idioma actual del navegador
Si queremos que el idioma de nuestra aplicación sea el del navegador, podemos emplear el objeto navigator
del navegador para obtenerlo y así acceder al idioma configurado por el usuario (líneas 6 y 7 de la siguiente pieza de código):

Si queremos ahorrarnos esta comprobación, la librería cuenta con el plugin i18next-browser-languagedetector
que establecerá el idioma de la aplicación de forma automática, recordando además esta selección en el local storage del navegador para próximas visitas (algo que es muy útil si el usuario posteriormente cambia de idioma). El plugin podemos instalarlo mediante yarn:
yarn add i18next-browser-languagedetector
Y en donde estemos configurando la librería importarlo y pasárselo a la librería i18next
por medio del método use
:
...
import LanguageDetector from 'i18next-browser-languagedetector';i18n.use(LanguageDetector).
...
Muy muy fácil como véis.
🔁 Traduciendo por medio de la librería i18next
El uso de esta librería es muy simple tal y como comentaba al comienzo del artículo. Además gracias a que cuenta con soporte completo para los hooks comenzar a traducir textos es prácticamente inmediato. Por ejemplo, supongamos que queremos traducir el título de nuestra página. Bastará para ello un código similar al siguiente:

En la línea 6 emplearemos el hook useTranslation
para obtener la función t
la cual nos permite traducir textos especificando la clave de esa traducción. En nuestro caso, puesto que estamos escribiendo t('title')
lo que obtendremos será “Bienvenido a React” (recordad que en el paso anterior escogimos español como idioma inicial).
Anidar traducciones
En la definición de las traducciones podemos también anidar las claves de modo que podamos agrupar las traducciones asociadas a una determinada vista o concepto de nuestra aplicación:

Si usamos esta técnica, cuando empleemos la función t
, accederemos a la traducción para “title” del siguiente modo:
t('welcome.title')
🔡 Interpolación
Por supuesto no sólo podemos especificar textos planos en nuestras traducciones, sino que también podemos añadir variables a los mismos que posteriormente la librería interpolará por medio de la función t
procedente del hook useTranslation
.
Por ejemplo, supongamos que queremos añadir el nombre de la persona al saludo inicial. En nuestro archivo de configuración especificaremos la variable rodeándola entre dobles corchetes como sucede en las líneas 12 y 17 del siguiente código:

Y a continuación, cuando vayamos a emplear la función t
, pasaremos el valor de name
del siguiente modo:

Fácil, ¿verdad?
🔛 Acceder al idioma actual y modificarlo
El hook useTranslation
no sólo nos provee de la función de traducción t
perteneciente a la librería i18next sino que también nos da acceso al objeto i18n
.
const {t, i18n} = useTranslation();
Este objeto posee dos características básicas:
- Su propiedad
language
, que nos permite obtener el idioma actual (i18n.language
) - Su método
changeLanguage
que nos permite modificar el idioma actual (es decir, es el método que emplearemos para el típico selector de idioma). Y sí, esto provocará un rerender de la interfaz de modo que en el momento en que lo invoquemos veremos como se modifica el idioma de todos los textos que estén siendo imprimidos por medio de la funciónt
.
🗂 Llevando las traducciones a archivos
Todo esto está muy bien, pero en el momento en que la cantidad de textos para traducir crece no es sostenible irlos añadiendo a la propiedad resources
del objeto que pasamos al método init
. Primero por legibilidad (imaginad el tamaño que podría alcanzar) y segundo por optimización, ya que probablemente muchas de las traducciones que inicialmente estaríamos cargando no las usaríamos y sin embargo estarían ocupando espacio.
Para resolver esto la librería i18next nos permite separar las traducciones en distintos archivos json
los cuales son considerados “namespaces”.
Lo primero que haremos será instalar la librería i18next http backend:
yarn add i18next-http-backend
Esta librería nos permite acceder de forma transparente por medio de la API Fetch a nuestros archivos de traducciones de modo que:
- Inicialmente sólo se cargarán aquellos archivos que solicitemos en el primer render.
- A medida que el usuario navegue por la aplicación la librería los irá solicitando de forma transparente.
A continuación, modificaremos el archivo donde se encontraba la configuración de la librería i18next para emplear este plugin por medio del método use
(línea 10):

Ya sólo nos quedan tres pasos más:
- Añadir los archivos de traducciones dentro de la carpeta
public
. - Importar en el hook
useTransalation
los namespaces definidos por los archivos de traducciones. - Añadir el componente
<Suspense>
para la carga asíncrona de estos archivos.
Vamos a ver cada paso.
Archivos de traducciones
En la carpeta public
del proyecto crearemos una carpeta llamada locales
donde habrá tantas carpetas como idiomas tenga nuestra aplicación. En nuestro caso, dentro de locales
se encontrarán las carpetas es
y en
. Dentro de ella, crearemos archivos JSON que albergarán las traducciones de nuestra aplicación (recordad que podemos anidar las traducciones del mismo modo que hacíamos en el objeto resources
que pasábamos al método init
) y cuyo nombre representará el namespace que necesitaremos especificar para que el plugin i18next-http-backend pueda cargarlo.
Siguiendo con nuestro ejemplo, tendremos un archivo public/locales/es/welcome.json
:
{
"title": "Bienvenido {{ name }}"
}
y otro archivo public/locales/en/welcome.json
:
{
"title": "Welcome {{ name }}"
}
Pasando namespaces a useTranslation
Y ahora, en vez de usar el hook useTranslation
sin argumentos, lo que haremos será invocarlo del siguiente modo:

Es decir, pasaremos un array con todos los namespaces que queremos que se carguen, lo cual hará que de forma automágica el plugin i18next-http-backend realice las llamadas oportunas para obtener esos archivos, cargar las traducciones en a librería y permitirnos así separar los textos de nuestras traducciones para optimizar el rendimiento de la aplicación.
Suspense
Finalmente, y puesto que para que podamos usar el hook useTranslation
es necesario que las traducciones estén cargadas (cosa que ahora estamos haciendo de modo asíncrono gracias al plugin i18next http backend) deberemos envolver nuestra aplicación con el componente <Suspense>
para mostrar el estado “cargando” mientras los archivo json con las traducciones se recuperan:

Y ahora sí, ya tenemos funcionando por completo nuestra aplicación con traducciones.
Repositorio
Os dejo un enlace al repositorio que he preparado sobre este artículo para que podáis ver en funcionamiento lo que os he comentado en este artículo:
Conclusiones
Este artículo es tan sólo una introducción a la librería i18next y su adaptación para React. Sin embargo, posee numerosas características además de las que he mencionado por lo que os recomiendo que visitéis su documentación (la cual por desgracia no está todo lo bien estructurada que debiera lo cual es su punto más débil) para descubrir todo lo que puede ofreceros.
Para mí es la mejor librería para incorporar traducciones a las aplicaciones por su sencillez a la hora de usarla y las opciones que ofrece.
Apóyame en Patreon
🧡🧡🧡 Gracias a: Ktron, Joseba, Alex y Jorge.
¿Quieres recibir más artículos como este?
Si te ha gustado este artículo te animo a que te suscribas a la newsletter que envío cada domingo con publicaciones similares a esta y más contenido recomendado: 👇👇👇