Internacionalización mediante atributos en Javascript

¡Maldita sea, Billy! ¡nuestro sitio web tiene que estar en varios idiomas! ¡Hazlo!.

Eso lo oiréis muchas veces en vuestra vida si sois parte de un servicio web y, seguramente en vuestros proyectos, hayáis buscado librerías o formas de hacerlo ya que no queréis repetir o tener todas las paginas varias veces (es decir, el sitio entero) en cada uno de los idiomas, con todo lo que supone eso.

Por eso tiene que existir una solución más sencilla, Jhonny, tiene que existir.

El tener una web multi idioma no es una cosa banal. Independientemente de lo que haya detrás para tener todos los idiomas al final, en la mayoría de los gestores, acabas duplicando las paginas convirtiendo tu aplicación web en un embrollo difícil de mantener. Por suerte el Javascript ha venido a tu rescate.

Spolier: no es una solución perfecta, esto es solo una introducción.

La página

Veamos un simple ejemplo:

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title data-i18n-es="Cambiar idioma" data-i18n-en="Change Language" data-i18n-it="Cambia lingua">Change Language</title>
  </head>
  <body>

    <a onClick="changelang('es')" href="#">ES</a> | <a onClick="changelang('en')" href="#">EN</a> | <a onClick="changelang('it')" href="#">IT</a>
    <br />
    <p data-i18n-es="Hola" data-i18n-en="Hello" data-i18n-it="Ciao">Hello</p>

    <script>
      const lang = document.documentElement.lang;

      function changelang(lang) {
        console.log('Changing lang to '+lang);
        document.documentElement.lang = lang;

        // Only body Commented
        // let elements = document.body.getElementsByTagName('*');

        // All elements
        let elements = document.documentElement.getElementsByTagName('*');

        for (var i = 0; i<elements.length; i++) {
          if (elements[i].getAttribute('data-i18n-'+lang)) {
            elements[i].innerHTML = elements[i].getAttribute('data-i18n-'+lang);
          }
        }

      }
    </script>
  </body>
</html>

En el ejemplo anterior podemos observar dos cosas graciosas:

La primera es que muchos tags tienen propiedades nuevas, una llamada data-i18n (en este caso el p y el title).
La segunda es que hay un script en javascript.

Los atributos como base

Bien. Como forma sencilla vamos a aprovecharnos de una "propiedad" de los tags muy curiosa y es que podemos crearles propiedades/atributos nuevas que el navegador va a pasar de ellas pero que nosotros podemos usarlo para lo que nos interese.

¿Y para que nos interesa? pues hombre, podemos usar un atributo especial que incluya el texto en los idiomas que queremos que estén. Simple. De ahi que si veis el atributo data-i18n-es contiene los textos en castellano, el data-i18n-en en ingles y el data-i18n-it en italiano.

El javascript para el cambio

Ahora bien, si tuviéramos una forma de recorrer todos los tags de la pagina, leer el atributo del idioma que deseásemos y ponerlo en el tag, tendríamos, en una única página todas las traducciones de golpe.

Hombre, pues para eso esta el Javascript.

Como veis tenemos una función que hace eso. Le pasamos como parámetros el lenguaje y simplemente lo que hace es recorrer todos los tags (hay dos formas, según lo que queramos conseguir), leer su data-i18n según el lenguaje y simplemente, cambiar el contenido.

Ademas, para ser sintacticamente (HTML) correctos, también cambiamos el language de la página en si.

Listo, todo solucionado.

Problemas

Obviamente, esta sencilla solución en la cual con una única página la tendremos para todos los idiomas que queramos poner (sin hablar mucho con el backend, salvo una única vez) puede ser un poco tediosa para cosas como aquellas en las que tengamos que cambias los propios atributos de los tags. ¿Un ejemplo?, las imágenes que tienen su alt.

Pero como todo, tampoco es complicado mejorar la versión de la función para que detecte eso y lo haga (aparte de cambiar el SRC de la imagen, si queremos y por lo tanto mostrar otra en otro idioma).

Como vemos, una solución rápida, sencilla y elegante para un pequeño problema.

Existen otras soluciones que se pueden realizar mediante CSS (si, usando el selector ::lang) y leyendo el atributo mediante [data-i18n-{lenguaje}] pero al final requieren de javascript para que la cosa no se desmadre.

tuti

Técnico en Comunicación Interna de la UVa

Deja un comentario

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.