Lo primero que debemos tener en cuenta es que nuestra web debe contar con un sistema de cookies o variables de navegador que permita guardar el idioma seleccionado por el usuario. En mi ejemplo también debemos contar con archivos JSON (1 por cada idioma) donde tengamos todas las traducciones realizadas.
A continuación te resumo cómo hago yo para cambiar el idioma de forma reactiva, es decir, sin necesidad de que refresque la web para ello. Todo esto, claro, tanto en el texto html, como en el inyectado através de PHP o JS. En este caso me centraré en el inyectado a través de PHP que bien suele ser alguna llamada desde AJAX.
El resumen sería el siguiente. Todas las etiquetas HTML que contengan o vayan a contener un texto, bien sean etiquetas "spam", "p" o directamente "div" van a tener una clase diferencial y numerada que representará el texto que se va a mostrar. Ejemplo "<span class="txt11"></span>" . En los archivos JSON van a estar esas variables con el texto correspondiente:
donde, por ejemplo:
En este caso las variables están llamadas con la "t" y el número diferencial. En mi caso lo he hecho así por otros motivos.
Una vez tenemos los JSON ya podemos proceder al tema. En todos los PHP donde queramos tener las traducciones incluiremos el siguiente código al comienzo:
include("./php/includes/_traducciones.php"); //incluimos lectura del json de tarducciones (en el index, al no ser módulo, no podemos usar la clase de js de traducciones)
$data = file_get_contents("./assets/json/".$idioma.".json"); //cogemos el json en una variable
$traducir = json_decode($data, true); //decodificamos el json
El include llama al archivo PHP donde recojo la cookie para saber qué JSON debo leer. Aquí el archivo _traducciones.php donde de existir cookie de idiomas nos quedamos con su valor o en su defecto establezco el idioma euskera.
if(!isset($_COOKIE['idiomas'])){
$idioma="eu"; //si no existe o está vacía la cookie de idiomas la ponemos en eu por defecto
}else{
$idioma=$_COOKIE["idiomas"]; //cogemos la cookie desde php de idiomas
}
En los archivos PHP donde queramos incluir variables con el texto traducido haremos lo siguiente. Donde la variable $traducir["t92"] tendrá el valor deseado para ese placeholder en concreto. O el valor del botón enviar tendrá tambíén el texto en un idioma u otro ($traducir['t27'])
<div id="cfc" class="contenedor_form">
<div class="chatForm">
<input name="message" id="message" type="text" placeholder="<?= $traducir['t92']?>" class="escribir prevenir-envio">
<input id="send-message" type="button" class="botonChat prevenir-envio" value="<?= $traducir['t27']?>">
</div>
</div>
o en este otro caso, donde además de poner el valor de la variable PHP de la traducción, establecemos la clase para que haya reacctividad al cambiar el idioma sin necesidad de refresco de la web.
websocket.onopen = function(ev) { //server
msgBox.append('<div class="system_msg" style="color:#bbbbbb"><span class="txt87"><?= $traducir['t87']?></span><!-- bienvenido al chat --></div>'); //notify user
}
y así sucesivamente en todos los textos que sean inyectados a través de PHP.
Cada vez que cambiemos entre idiomas lanzaremos un evento click que recogeremos con JS. Si queremos la reactividad del cambio de idioma, deberemos recoger la variable de cookie de idiomas y ller el JSON desde JS. Después haremos una iteración por todas las clases que tengan "txt" y cambiaremos su valor HTML por el del JSON:
let jsonIdioma = "";
jsonIdioma = `assets/json/${idioma}.json`;
//RECOGEMOS TODOS LOS ELEMENTOS DEL JSON
fetch(jsonIdioma)
.then(response =>{
if(response.ok)
return response.text()
else
throw new Error(response.status);
})
.then(data =>{
//PARSEAMOS EL JSON EN UN OBJETO
const iJs=JSON.parse(data);
//RECORREMOS LAS PROPIEDADES DE LAS CLAVES DEL OBJETO
for (var clave in iJs){
//SI HAY PROPIEDAD EN ESA CLAVE, ENTRAMOS
if (iJs.hasOwnProperty(clave)) {
//ESCRIBIMOS HTML DE LAS CLAVES Y EL VALOR DE LAS CLAVES
/* console.log("2- Clave: " + clave + " - Valor: " + iJs[clave]); */
if (document.querySelector(`.tx${clave}`) || document.querySelector(`.${clave}`)){ //si existe elemento html con clase de traducción txt o cat
for(const item of document.querySelectorAll(`.tx${clave}`)){ //recorremos todos los elementos html con esa clase txt
item.innerHTML=iJs[clave];//le cambiamos el valor html con la nueva traducción
}
for(const item of document.querySelectorAll(`.${clave}`)){ //recorremos todos los elementos html con esa clase cat
item.innerHTML=iJs[clave];//le cambiamos el valor html con la nueva traducción
}
}
}
}
console.log("3- json de idioma establecido en: "+ idioma);
})
.catch(err =>{
console.error("ERROR", err.message)
});
De esta forma, cuando haya un click en un idioma este se recogerá desde JS y se procederá a la lectura del json correspondiente y al cambio de todos los HTML que tengan dicha clase. Obviamente habrá traducciones que, al no contener clase, como el placeholder o el value de un botón, se queden fuera de esa reactividad, pero para ello haremos excepciones en el mismo evento click de JS:
//CAMBIAMOS EL IDIOMA EN LOS PLACEHOLDER, QUE NO SE PUEDE YA QUE NO SE LES PUEDE ASIGNAR CLASE DE IDIOMA
if(document.getElementById("message")){
document.getElementById("message").placeholder=traduccion.traducir("t92") //escribe aquí tu mensaje, (placeholder del input del chat)
};
if(document.getElementById("send-message")){
document.getElementById("send-message").value=traduccion.traducir("t27") //enviar, (value del botón enviar del chat)
};
if(document.getElementById("idbuscatext")){
document.getElementById("idbuscatext").placeholder=traduccion.traducir("t97") //busca por palabras clave.., (placeholder del input del buscador de empleo o cursos)
};
//CAMBIAMOS LOS DATA-NOMBRE DE LAS CATEGORÍAS DEL FORO
if(document.getElementById("foroID")){
var n=9 // iteramos 8 veces, (9 en total) para cambiar los nombres de las cat en el foro <<<<< según se añadan cat hay que incrementar valor de n, siempre que en el json estén en orden del 1 al n
for(var i=1;i<=n;i++){
if(document.querySelector(`.cat${i}`)){
for(const item of document.querySelectorAll(`.cat${i}`)){ //recorremos todos los elementos html con esa clase
item.dataset.nombre=`${traduccion.traducir(`cat${i}`)}`
}
}
}
}
de esta forma, incluso esos elementros serán reactivos y cambiarán de idioma nada más el usuario lo seleccione.
Cualquier duda, deja tus comentarios!