Al momento de ofrecer el contenido de tu aplicación en varios idiomas, existen varias opciones.

Por ejemplo, Chrome ofrece la posibilidad de traducir el contenido de una página siempre que el idioma declarado en el atributo lang del fichero HTML sea distinto del navegador del usuario. En ocasiones el idioma de la página coincide con el del navegador pero el contenido está en otro idioma, por lo que no es un método muy eficiente.

Existen varias librerías para este cometido en distintos lenguajes. Vamos a usar una librería que tiene soporte con varias lenguajes y tecnologías como js o php. Al estar realizada en JS tiene una gran compatibilidad con frameworks realizados en este lenguaje, veremos su utilización en react.

i18next es un framework de traducción realizado en JS que nos permitirá configurar varias opciones referentes a la traducción. Vamos a ver la configuración inicial y una serie de opciones útiles, como la elección automática del idioma de nuestra aplicación o la posibilidad de que el usuario pueda cambiar el idioma a su elección.

Instalación

Para empezar deberemos instalar la librería de i18next y la de su integración con react dentro de nuestro proyecto react.

npm install --save i18next
npm install --save react-i18next

Configuración

Creamos en src una carpeta donde guardaremos todos los ficheros relacionados con la librería. También creamos un fichero .js donde realizaremos la configuración de la librería para nuestra aplicación.

tree-config

Para utilizar la librería en nuestro proyecto deberemos importar en el index de nuestra aplicación el fichero de importación que previamente hemos creado.

index

Ahora nos centraremos en la configuración de la librería. Importamos el objeto i18n y la librería de react.

import i18n from 'i18next;
import { initReactI18next } from 'react-i18next;

Con el objeto i18n realizaremos la configuración. Mediante el método use() le indicamos que librería usar, le pasamos como parámetro la librería de react.

i18n.use(initReactI18next)

El método init() nos permitirá configurar propiedades referentes a la traducción mediante un objeto JSON que le pasaremos como parámetro. Este método deberá ir después de la llamada al método use.

i18n
    .use(initReactI18next)
    .init({
        interpolation : {
            escapeValue : false
        },
        lng : "en",
        fallbackLng : "en",
        resources : {
            en : {
                translation : {
                    "message" : "Hello world!"
                }
            },
            es : {
                translation : {
                   "message" : "¡Hola mundo!"
                }
            }
        }
    });

Vamos a explicar los parámetros que hemos configurado.

  • lgn => indica el idioma a establecer por defecto
  • fallbackLng => establece un idioma si no hubiera traducción del idioma establecido por defecto
  • resources  => indica la traducciones disponibles y se agrupan por idiomas.

Una vez configurada la librería procedemos a usarla en nuestra aplicación. Importamos en el componente deseado el hook useTranslation que nos permitirá obtener una función.

import { useTranslation } from 'react-i18next';

El componente sobre el que trabajaremos será App, en ella obteneremos la función t mediante el hook.

const { t } = useTranslation();

La función t nos permitirá traducir textos indicándole una clave. Esta clave será leída de las traducciones creadas anteriormente. Si le pasamos la clave message nos devolverá Hello world! debido a que establecimos el inglés como idioma por defecto.

<p>{ t('message') }
</p>
ingles

Detección del idioma

Con lo configurado anteriormente podemos cambiar el idioma que queremos usar en nuestra página pero lo hacemos de forma estática, es decir, el usuario verá la página en el idioma que hemos establecido y no podrá cambiarlo.

Una solución es cambiar el idioma automáticamente, detectando el idioma del navegador del usuario. Para ello usamos navigator.language, que nos deolverá lo siguiente.

navigatorlanguage

Solo necesitamos los dos primeros caracteres, por lo que podemos extraerlos y pasárselo como parámetro al objeto de configuración.

// FICHERO DE CONFIGURACIÓN
const userLang = navigator.language.substring(0, 2);

// Esto iría dentro del objeto que le pasamos al método init del objeto i18n
lng : userLang

La librería de i18next tiene un plugin que nos realiza esta consulta automáticamente y además nos lo guarda en el local storage, lo cual nos será util si queremos que el usario pueda cambiar el idioma y no pierda la traducción en cada recarga de la página.

Deberemos instalar el plugin dentro de nuestro proyecto y después importarlo en el fichero de configuración.

// Instrucción de instalación
npm install --save i18next-browser-languagedetector

// Importación
import LanguageDetector from 'i18next-browser-languagedetector';

Eliminamos la propiedad lng, ya que el plugin se encargará de darle un valor. El objeto i18n nos quedará así.

i18n
    .use(initReactI18next)
    .use(LanguageDetector)
    .init({
        interpolation : {
            escapeValue : false
        },
        fallbackLng : "en",
        resources : {
            en : {
                translation : {
                    "message" : "Hello world!"
                }
            },
            es : {
                translation : {
                   "message" : "¡Hola mundo!"
                }
            }
        }
    });

Si lanzamos nuestra aplicación, ahora estará en el mismo idioma que el del navegador.

ingles

Cambiar idioma

Si bien lo que hemos realizado hasta ahora es útil, sería conveniente dejarle al usuario elegir el idioma de la página.

El hook que importamos en el fichero de configuración no solo nos ofrece la función t, si no también el objeto i18n.

const { t, i18n } = useTranslation();

Este objeto tiene la propiedad language, que nos permite obtener el lenguaje actual y el método changeLanguage, con el que podremos cambiar el idioma actual.

<p>
  Idioma de la app : { i18n.language }
</p>
<button onClick={ () => i18n.changeLanguage("es") }>ES</button>
<button onClick={ () => i18n.changeLanguage("en") }>EN</button>

Si lanzamos nuestra aplicación, podremos cambiar el idioma dinámicamente.

react

Archivos JSON

Tener las traducciones en el fichero de configuración puede estar bien al principio pero según va creciendo el código de nuestra aplicación la lectura del fichero será más difícil por lo que lo más óptimo sería tener archivos con las traducciones.

Instalamos el plugin de i18next y lo importamos en el fichero de configuración.

// Instrucción de instalación
npm install --save i18next-http-backend

// Importación
import Backend from 'i18next-http-backend';

Indicamos al objeto i18n que vamos a usar el plugin y eliminamos la propiedad resources que contenía las traducciones.

i18n
    .use(initReactI18next)
    .use(LanguageDetector)
    .use(Backend)
    .init({
        interpolation : {
            escapeValue : false
        },
        fallbackLng : "en",
    });

Ahora las traduciones las colocaremos en archivos JSON. En la carpeta public creamos la carpeta locales, que contendrá una carpeta por idioma y dentro de estas colocaremos los distintos ficheros JSON.

raiz

Los ficheros quedarán de la siguiente forma.

// en/global.json
{ 
    "message" : "Hello world!"
}

// es/global.json
{ 
    "message" : "¡Hola mundo!"
}

Como ahora tenemos varios archivos de traducción debemos indicar al hook useTranslation que archivo va a leer.

const { t, i18n } = useTranslation(['global']);

Para acabar, deberemos envolver nuestro componente bajo el componente Suspense para evitar errores a la hora de la carga de los ficheros de traducción. Para usar el componente Suspense deberemos importarlo.

El componente sobre el que hemos trabajado quedará así.

import { useTranslation } from 'react-i18next';
import React, { Suspense } from 'react';

function Foo() {
  const { t, i18n } = useTranslation(['global']);
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          { t('message') }
        </p>
        <p>
            Idioma de la app : { i18n.language }
          </p>
          <button onClick={ () => i18n.changeLanguage("es") }>ES</button>
          <button onClick={ () => i18n.changeLanguage("en") }>EN</button>
      </header>
    </div>
  );
}

function App() {
  return (
    <Suspense fallback="cargando...">
      <Foo />
    </Suspense>
  );
}

export default App;

El resultado será el mismo que el anterior, la única diferencia será la organización de las traducciones.

Conclusiones

I18next es un framework sencillo de usar y accesible debido a su escalabilidad, podiendo usarse tanto en proyectos muy sencillos como en unos más complejos.

Hemos visto una pequeña introducción en el uso de este framework pero i18next nos ofrece más opciones de las que hemos visto en esta publicación.

Algunas ampliaciones que podríamos aplicar al contenido visto sería el desarrollo de más idiomas, con más ficheros JSON y con mucho más contenido, aplicarlo a una apliación ya terminada o cambiar el atributo lang del documento HTML al cambiar el idioma.


Autor/a: Gerard Alexander Nina Picón

Curso: Desarrollo Web Full Stack, MultiCloud y Multiplataforma

Centro: Tajamar

Año académico: 2020-2021

Código: https://github.com/GerardNP/react-translate

Leave a Comment

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.