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.

