El sistema en si es muy sencillo y, por tanto, relativamente limitado pero apto para el 90% de las necesidades.
Veamos cómo funciona:
Cada página tiene su propio array que contiene los id de las etiquetas que deben modificarse por el gestor de idioma y la propiedad que va a manipularse, o null si no se manipula ninguna propiedad, como en el caso de los alerts.
Por ejemplo, una página con los siguientes elementos:
Código HTML:
<body> <h1 id="textoTitular">xxxxx</h1> <p id="parrafoInterior">xxxxxxxxx</p> <form> <select> <option id="textoOption1" value="xxxxxx">xxxxxxxxxxx</option>"; <option id="textoOption2" value="xxxxxx">xxxxxxxxxxx</option>"; </select> <input id="textoBoton" name="textoBoton" type="submit" value="xxxxx" /> </form> <script type="text/javascript">alert (Lang.textoAlert)</script> </body>
Código:
La página también contendrá una variable llamada idioma (var idioma="esp"), que contiene un string que identifica al idioma seleccionado.LangPack = new Array ( 'textoTitular','innerHTML', 'parrafoInterior','innerHTML', 'textoBoton','value', 'textoOption1','value', 'textoOption2','value', 'textoAlert',null )
Si usamos php para propagar el idioma a la sesion, antes del head introduciremos lo siguiente:
Código PHP:
<? session_start(); ?>
<? $_SESSION['lang']||$_SESSION['lang']="esp"; ?>
En el head de la página incorporaremos lo siguiente:
Código:
Hasta aquí, la parte que varía de una página a otra.<script type="text/javascript"> // Recojo el idioma de una variable de sesion PHP var idioma='<? echo $_SESSION['lang']; ?>'; // Creo el array necesario LangPack = new Array ( 'textoTitular','innerHTML', 'parrafoInterior','innerHTML', 'textoBoton','value', 'textoOption1','value', 'textoOption2','value', 'textoAlert',null ) ; </script>
Los elementos comunes a todas las páginas son tres, y nos limitaremos a llamarlos en todas las páginas:
Colocaremos los dos primeros en el head:
<script type="text/javascript" src="includes/ajax.js"></script>
<script type="text/javascript" src="includes/langpack.js"></script>
Y el último lo situaremos donde queramos situar el select para cambiar de idioma
<? include("includes/cambialang.php"); ?>
Yo hago el cambio de idima mediante un select, pero cualquier otro sistema es tan válido como este.
Código PHP:
<select id="selidioma" size="1" onchange="idiomaCambia(1)">
<?
$path="lang/"; // Path al directorio donde se encuentran las páginas que ofrecen los datos de idiomas
$directori=dir($path);
while ($arxiu = $directori->read()) { // leemos secuencialmente los archivos del directorio...
if(substr($arxiu,0,5)=="lang_") { // ... y descartamos aquellos que no empiezan por "lang_"
$arxiu=substr($arxiu,5,3); //tomamos el código de idioma
echo "<option value='$arxiu'"; // y lo mostramos en un option
if ($arxiu==$_SESSION['lang']) { echo "selected='selected'"; } // Si tenemos una variable php de sesion con el idioma actrual, muestra esta opcion como seleccionada
echo ">$arxiu </option>"; // Y cerramos el option
}
}
$directori->close();
?>
</select>
<body onload="carregaIdioma()">
Ya no es necesario saber nada más para lograr que funcione.
A continuación está el código de ajax.js y de langpack.js. Lo he comentado para que el que quiera comprender el funcionamiento del sistema y/o quiera modificarlo a su gusto pueda hacerlo.
ajax.js Es simplemente un script de conexión y contiene el siguiente código:
Código:
metodo: get/postfunction cargaDatos(metodo,url,modo,funcion,funcionError) { if (!funcionError) { funcionError=funcion; } var req; if(window.XMLHttpRequest) { try { req = new XMLHttpRequest(); } catch(e) { req = false; } } else if(window.ActiveXObject) { try { req = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { req = false; } } if (req) { req.open(metodo,url,modo); req.onreadystatechange = function() { if (req.readyState == 4 && req.status==200) { funcion(req); } else if (req.readyState == 4) { funcionError(req); } } req.send(); } else { req= new Object (); req.status=999; req.statusText="No se ha creado XMLHttpRequest"; funcionError(req); } }
url: la url que contiene los datos
modo: true/false (asíncrono / sincrónico)
funcion: la función que se llama si el proceso tiene éxito.
funcionError: la función que se llama si el poroceso falla, en caso de no definirse este parámetro, en caso de fallo se llama a funcion.
langpack.js Contiene el siguiente código:
Código:
El nombre de los archivos de idiomas, en mi caso, tienen la siguiente estructura "lang_xxx.php" donde xxx es un codigo de tres letras para cada idioma (esp, eng...).// En primer lugar creamos Lang, que va a ser el contenedor de los textos en el idioma solicitado. Cada uno de los textos estará disponible mediante Lang.nombreDelTexto var cadena = "var Lang = { "; for (var i=0; i<LangPack.length; i=i+2) { cadena+=LangPack[i]+" : '' , "; } eval(cadena.substr(0,cadena.length-2)+" }"); // Esta función se encargará de rellenar Lang con los valores almacenados en la página que contiene la información de cada idioma. // Básicamente la página servirá el objeto ya creado y esta función se limita a hacer un eval() de dicho string var idiomaActualitza = function (req) { var retorn=req.responseText; eval (retorn); } // Ahora ya podemos cargar el idioma. Para ello llamamos a la función idiomaCambia(param). // El parámetro 0 indica a la función que debe cargar el idioma definido en la variable idioma // El parámetro 1 indica que debe consultar primero el objeto select desde el que se puede seleccionar el idioma idiomaCambia(0); // function idiomaCambia(nou) { if (nou==1) { // Si se ha modificado el idioma, capturamos su nuevo valor en el select llamado "selidioma" que más tarde crearemos en la página. idioma=document.getElementById('selidioma').value; } var url="lang/lang_"+idioma+".php"; cargaDatos('GET',url,false,idiomaActualitza); if (nou==1) { // Si se ha modificado el idioma, recarga los valores carregaIdioma(); } } // Este bucle toma secuencialmente los valores del array LangPack y crea un string del tipo documentGetElementById[nombredelelemento].propiedad=nuevovalor que después es procesado mediante eval() // Hay que notar que, para simplificar, es necesario que tanto la etiqueta como la variable que contiene el texto a insertar deben tener el mismo nombre // Así, el elemento id="textoAyuda" será cargado con el texto contenido en Lang.textoAyuda function carregaIdioma() { for (var i=0; i<LangPack.length; i=i+2) { if (LangPack[i+1]!=null) { eval ("document.getElementById('"+LangPack[i]+"')."+LangPack[i+1]+"=Lang."+LangPack[i]); } } }
Los archivos correspondientes a los idiomas son extremadamente sencillos y fáciles de manipular y tienen la siguiente forma:
Código:
Primero abrimos sesion y modificamos la variable de sesion lang para que el idioma seleccionado esté disponible para toda la sesion.<? session_start(); ?> <? $_SESSION['lang']='esp'; ?> Lang = { // Texto generico TextAjuda : "Ayuda", TextTornar : "Volver", // Botones genericos TextInstalar : "Instalar", TextBorrar : "Borrar", // Instalador Configuracio : "Configuración", CarregarPaisos : "Cargar BBDD de paises", CarregarCarrers : "Cargar BBDD de calles", CarregarUbicacions : "Cargar BBDD de ubicaciones", CarregarCoordinades : "Cargar BBDD de coordenadas", CarregarDadesPaisos : "Cargar datos de los siguientes paises:", NomBaseDades : "Base de datos", Servidor : "Servidor", NomUsuari : "Nombre de usuario", ClauAcces : "Clave de acceso", RepetirClauAcces : "Repetir clave de acceso", AlertInstalaPaisos : "ATENCIÓN!!\nDesactivar esta casilla puede limitar la funcionalidad del gestor. Consulta el manual.", InstallTextError1: "ERROR!\nNo se han rellenado todos los datos necessarios", InstallTextError2: "ERROR!\nLas claves de acceso no coinciden", InstallTextError3: "ERROR!\nNo se ha logrado conectar con el servidor", //Legal TitulCondicionsLegals: "Condicions legales", TextCredits: "Créditos", TextColaboracio: "Se agradecerá cualquier colaboración qe ayude a mejorar este gestor. Será particularmente bienvenida cualquier aportación de bases de datos de datos de paises o listados que permitan confeccionar estas bases de datos. También serán muy bienvenidos ficheros de traducción a otros idiomas.", // Pie de pagina Idioma : "Idiona", WebSite : "WebSite", CondicionsLegals : "Condiciones Legales" }
El resto se devolverá como string a las funciones contenidas en langpack.js, que se encargará de evaluarlo.
Cada par de valores sigue el siguiente modelo:
id_de_la_etiqueta/nombre_de_la_variable : "texto a mostrar",
Recordemos que el id de la etiqueta y el nombre de la variable deben coincidir
Espero que le sea útil a alguien.