Creamos un selector de idioma en JavaScript
Hoy, vamos a hablar de cómo implementar un simple selector de idioma en el sitio web estático o básico, sin necesidad de ningún backend o llamadas a la base de datos o redirección a otra página. Vamos a utilizar sólo JavaScript, sin PHP u otros lenguajes de programación.
Servir contenido HTML en varios idiomas es un gran tema. Para empezar, lo que vamos a hacer es básicamente modificar las clases HTML mediante JavaScript para cambiar la apariencia de elementos HTML específicos en la página.
Para poder demostrarlo, hemos elegido una página web sencilla de un portafolio.
Ahora mostramos cómo hacer versiones en varios idiomas en un sitio web básico y cómo cambiar el contenido con JavaScript sin ningún backend, con la ventaja añadida de ser ligero y rápido. Cuando seleccionamos un idioma en nuestro elemento de cabecera, todo el contenido que hemos preparado cambiará a ese idioma.
Sin más retraso, entremos en materia.
Requisitos básicos
Seguramente para continuar, asumimos que los conocimientos de HTML, CSS y JavaScript pueden ser útiles.
Selectores de idioma en la cabecera
Digamos que tenemos una página sencilla con la cabecera, el cuerpo, etc. ya hechos, pero nos gustaría añadir opciones de idiomas. Primero creamos tres versiones de los idiomas que queremos tener >
<div class="languageContainer"> <div id="eng" class="languages british"><a>english</a></div> <div id="esp" class="languages spain"><p>español</p></div> <div id="svk" class="languages slovak"><p>slovensky</p></div> </div> <nav class="menu"> <a href="#about" class="eng" lang="en">About</a> <a href="#about" class="esp" lang="es">Acerca de</a> <a href="#about" class="svk" lang="sk">O mne</a> <a href="#work" class="eng" lang="en">My work</a> <a href="#work" class="esp" lang="es">Trabajos</a> <a href="#work" class="svk" lang="sk">Moja praca</a> <a href="#contact" class="eng" lang="en">Contact</a> <a href="#contact" class="esp" lang="es">Contacto</a> <a href="#contact" class="svk" lang="sk">Kontakt</a> </nav>
Ahora describimos lo que hemos hecho. Creamos el contenedor <div>
con una clase específica para contener y modificar visualmente su contenido por CSS(lo mostramos más adelante).
A continuación, tenemos 3 conjuntos de idiomas, cada uno tiene la clase language
, de nuevo para CSS, las clases british, spain, slovak
son para un conjunto de banderas que tomamos de Country Flags - A simple API to load any country flags.
También tenemos un atributo lang, que permitirá a los rastreadores de búsqueda saber que este contenido está en otro idioma, tratarán ese contenido de manera diferente, esto es para un mejor ranking.
El más importante es el atributo id, este sirve para la escucha de eventos - básicamente cuando el código JavaScript detecta que por ejemplo hemos hecho clic en uno de estos tres, ejecutará nuestro código.
CSS para el código HTML superior>
.languageContainer { display: flex; justify-content: end; overflow: visible; height: 3rem; font-size: small; } .languages { display:flex; align-items: center; margin:.2rem; padding: 0.5rem; color: #fff; cursor: pointer; } .languages::before { content: ''; display: block; width: 32px; height: 32px; } .british::before{ background:url("https://www.countryflags.io/gb/flat/32.png"); } .spain::before{ background:url("https://www.countryflags.io/es/flat/32.png"); } .slovak::before{ background:url("https://www.countryflags.io/sk/flat/32.png"); }
(Observe que con y la altura de los iconos en la clase languages::before
se correlaciona con el tamaño de la imagen que hemos establecido en el URL)
(Nota2 : fijamos un bonito puntero - la mano se mostrará cuando movamos el cursor del ratón por encima de la clase languages)
Alternativamente, podemos usar imágenes descargadas (iconos), estas son de flagpedia.net, para estar seguros de que nuestra página no se colgará cuando la fuente externa no esté disponible. Así que lo hicimos local como esto>
.british::before{ background:url('../img/flags/unitedkingdom32x32.png') } .spain::before{ background:url('../img/flags/spain32x32.png') } .slovak::before{ background:url('../img/flags/slovakia32x32.png') }
Parte de JavaScript
Ahora la parte de codificación. Necesitaríamos manipular la aparición o desaparición de esos elementos con diferentes textos. Para acceder a ellos, en nuestro archivo JavaScript creamos >
const selectedEnglish = document.getElementById("eng"); const selectedEspanol = document.getElementById("esp"); const selectedSlovensky = document.getElementById("svk"); const hidden = "display:none;"; const shown = "display:block;";
Las variables hidden
y shown
modificarán el estilo del elemento HTML desde este script.
Para acceder a todos los elementos con el mismo idioma, creamos este código>
const allEnglishText = document.getElementsByClassName("eng"); const allEspanolText = document.getElementsByClassName("esp"); const allSlovakText = document.getElementsByClassName("svk");
Ahora tenemos que reconocer lo que vamos a hacer con él. Necesitamos encender la versión de un idioma y al mismo tiempo apagar todas las demás versiones.
Esto se puede poner en la función, y tenemos que tener 3 funciones para cada versión de idioma. Por ejemplo :
allEnglishText
es una colección de todos los elementos HTML con el mismo nombre de clase eng
. En la función, recorremos todos esos elementos y establecemos el parámetro, o digamos el estilo a todos ellos, y de la misma manera, todas las otras versiones de idioma no se mostrarán en absoluto.
//SHOW ALL ENGLISH TEXT function showEnglishText() { for (element in allEnglishText) { allEnglishText[element].style = shown; } for (element in allEspanolText) { allEspanolText[element].style = hidden; } for (element in allSlovakText) { allSlovakText[element].style = hidden; } } //SHOW ALL SPANISH TEXT function showSpanishText() { for (element in allEnglishText) { allEnglishText[element].style = hidden; } for (element in allEspanolText) { allEspanolText[element].style = shown; } for (element in allSlovakText) { allSlovakText[element].style = hidden; } } //SHOW ALL SLOVAK TEXT function showSlovakText() { for (element in allEnglishText) { allEnglishText[element].style = hidden; } for (element in allEspanolText) { allEspanolText[element].style = hidden; } for (element in allSlovakText) { allSlovakText[element].style = shown; } }
Botones y EventListeners
Hasta ahora hemos creado todo el texto en HTML y las funciones para mostrarlas u ocultarlas, pero también necesitamos el switch para lanzar las funciones. Seguimos detrás del código anterior añadiendo esto>
//ENGLISH-> ALL OTHERS SWITCHED OFF selectedEnglish.addEventListener("click", () => { selectedEnglish.classList.add("langSelected"); selectedEspanol.classList.remove("langSelected"); selectedSlovensky.classList.remove("langSelected"); showEnglishText(); });
Para explicarlo, añadiendo un escuchador de eventos en el elemento almacenado en la variable selectedEnglish
--> ese es nuestro elemento en la cabecera con id=’eng’
, cuando hagamos clic en él con el ratón, se lanzará nuestra función showEnglishText()
y además tenemos un montón de código para añadirle una clase CSS, que contenga borde, para mostrar visualmente qué botón se ha pulsado en ese momento.
Por supuesto, tenemos que añadir todas las demás versiones>
//SPANISH-> ALL OTHERS SWITCHED OFF selectedEspanol.addEventListener("click", () => { selectedEspanol.classList.add("langSelected"); selectedEnglish.classList.remove("langSelected"); selectedSlovensky.classList.remove("langSelected"); showSpanishText(); }); //SLOVAK-> ALL OTHERS SWITCHED OFF selectedSlovensky.addEventListener("click", () => { selectedSlovensky.classList.add("langSelected"); selectedEspanol.classList.remove("langSelected"); selectedEnglish.classList.remove("langSelected"); showSlovakText(); });
Esto por sí solo sería suficiente para que funcione, pero hay un pequeño problema, hasta ahora seguimos viendo las 3 versiones por defecto, sólo después de hacer clic en el botón respectivo, se ocultan. Así que tenemos que asegurarnos de que por defecto sólo hay 1 visible llamando por ejemplo a la función showEnglishText()
detrás de la definición de las variables. Pero podemos mejorarlo como veremos en el próximo capítulo.
Mecanismo para almacenar el idioma seleccionado en el almacenamiento local(Local Storage)
Ahora daremos un paso más y almacenaremos el idioma elegido en el Local Storage del navegador del usuario. De esta manera, se le servirá al usuario el idioma que seleccionó por última vez. Esto significa que incluso si la página se actualiza, "recordará" la última selección. Creamos una entrada en el almacenamiento local utilizando localStorage.setItem()
en cada uno de los escuchadores de eventos, así>
//ENGLISH-> ALL OTHERS SWITCHED OFF selectedEnglish.addEventListener("click", () => { selectedEnglish.classList.add("langSelected"); selectedEspanol.classList.remove("langSelected"); selectedSlovensky.classList.remove("langSelected"); showEnglishText(); localStorage.setItem("languageActive", "english"); }); //SPANISH-> ALL OTHERS SWITCHED OFF selectedEspanol.addEventListener("click", () => { selectedEspanol.classList.add("langSelected"); selectedEnglish.classList.remove("langSelected"); selectedSlovensky.classList.remove("langSelected"); showSpanishText(); localStorage.setItem("languageActive", "espanol"); }); //SLOVAK-> ALL OTHERS SWITCHED OFF selectedSlovensky.addEventListener("click", () => { selectedSlovensky.classList.add("langSelected"); selectedEspanol.classList.remove("langSelected"); selectedEnglish.classList.remove("langSelected"); showSlovakText(); localStorage.setItem("languageActive", "slovak"); });
De esta forma tendremos almacenado bajo el id languageActive
la versión del idioma que acabamos de pulsar. Ahora es el momento de escribir el código para recuperar esta información del almacenamiento local. Y así es como>
//LOCAL STORAGE ADDON switch (localStorage.getItem("languageActive")) { case "english": selectedEnglish.classList.add("langSelected"); showEnglishText(); break; case "espanol": selectedEspanol.classList.add("langSelected"); showSpanishText(); break; case "slovak": selectedSlovensky.classList.add("langSelected"); //console.log("slovak on"); showSlovakText(); break; default: //default ENGLISH text shown, all others disabled //default -> no local storage exists selectedEnglish.classList.add("langSelected"); showEnglishText(); }
Por defecto - si no pudimos recuperar nada del Almacenamiento Local, por ejemplo, el usuario es la primera vez en su sitio, se lanzará el código default
. Elegimos el inglés para que se muestre primero.
Cuando hay una entrada encontrada, switch reconocerá el valor y llamará a la función respectiva.
Conclusión
Os hemos mostrado cómo hacer un cambio de idioma muy básico y esperamos que os haya gustado.
Lo mejor sería hacer saber al buscador que tenemos versiones localizadas del texto en nuestra página, para que no traten el texto traducido como duplicado. Porque eso puede llevar a un montón de contenido aplicado y eso a su vez puede llevar a un ranking más bajo en los motores de búsqueda.
Seguramente podemos mejorar esto, por ejemplo poniendo todo el contenido del texto (todas las traducciones también) en un objeto y seleccionando la versión deseada del texto desde él con un código que recupere el valor de la clave, pero eso lo haremos en otro artículo. Hasta pronto.
Imágenes de Tibor Kopca