Las páginas que acostumbramos visitar, suelen estar en un solo idioma, aunque en ocasiones encontramos una serie de banderitas indicando que existe una versión de la misma disponible en otra lengua.
Cuando una página tiene poco contenido y una serie limitada de traducciones, podemos incluir en la misma las distintas traducciones, mostrando solamente la versión que el usuario seleccione.
Una forma sencilla de implementar un sistema de estas características sería usando una capa para cada idioma y unos botones (tal vez con banderitas) que oculten en principio la capa visible, y seguidamente muestre la correspondiente al idioma seleccionado.
<script type="text/javascript" > var idioma = "hispano"; function ponerIdioma(cual) { document.getElementById(idioma).style.display = "none"; idioma = cual; document.getElementById(idioma).style.display = "block"; } </script>
En el cuerpo de la página ponemos los botones y las capas:
<button type="button" onclick="ponerIdioma('hispano')" > Español </button> <button type="button" onclick="ponerIdioma('english')" > Inglés </button> <button type="button" onclick="ponerIdioma('francoise')" > Francés </button> ... <div id="hispano" > <-- Aquí el contenido en español --> </div> <div id="english" > <-- Aquí el contenido en inglés --> </div> <div id="francoise" > <-- Aquí el contenido en francés --> </div> ...
Pero no siempre es tan fácil implementar una página de estas características. Supongamos que tenemos que implementar una página con un formulario, si ponemos una copia del formulario para cada idioma, lo que el usuario escriba o seleccione en un campo debe repetirlo cada vez que cambie de idioma... ¡sí!, es una situación realmente anómala, pero no debemos descartarla.
Para solucionar este problema, replicaremos cada descriptor de campo para cada idioma (etiquetas label). Si queremos un campo para el nombre, podemos definirlo así:
<label id="es_nombre" for="nombre" >Nombre</label> <label id="en_nombre" for="nombre" >Full Name</label> <label id="fr_nombre" for="nombre" >Nom et Prénoms</label> <input type="text" name="nombre" id="nombre" />
Sin duda usaremos varios campos, así que tenemos que resolver una ocultación/visualización múltiple de elementos, que vamos a implementar con un arreglo (array).
Un título descriptivo pero algo complejo, aunque con un simple ejemplo se puede explicar.
Partiendo de que vamos a hacer una página de tres idiomas, y entre otros campos tenemos nombre, teléfono y comentario, podemos hacer un array de etiquetas tal como sigue:
var etiquetas = new Array("nombre", "telefono", "comentario");
Pero si esa variable "etiquetas" es a la vez un array asociado al idioma, tendremos una estructura muy comprensible, y a la vez muy útil.
var etiquetas = new Array(); etiquetas["hispano"] = new Array("es_nombre", "es_telefono", "es_comentario"); etiquetas["english"] = new Array("en_nombre", "en_telefono", "en_comentario"); etiquetas["francoise"] = new Array("fr_nombre", "fr_telefono", "fr_comentario");
Con estos cambios, el método original "ponerIdioma()", no nos sirve, pero con unos pocos retoques conseguimos una total funcionalidad.
function ponerIdioma(cual) { document.getElementById(idioma).style.display = "none"; for (var i = 0, total = etiquetas[idioma].length; i < total; i ++) document.getElementById(etiquetas[idioma][i]).style.display = "none"; idioma = cual; document.getElementById(idioma).style.display = "block"; for (var i = 0, total = etiquetas[idioma].length; i < total; i ++) document.getElementById(etiquetas[idioma][i]).style.display = "inline"; }
También es preciso aclarar que los campos de los idiomas inactivos deben estar ocultos desde el principio, y visibles los correspondientes al lenguaje activo usando el estilo display none/inline.
Ya hemos visto que podemos mostrar/ocultar elementos en línea o elementos de bloque, pero a veces no es suficiente cuando se trata de elementos especiales (optgroup, legend, botones...) en donde en lugar de cambiar la visibilidad, es preciso cambiar el contenido; para ello podemos contar con otros trucos igualmente efectivos (usar innerHTML, clonar y reemplazar los elementos usando métodos DOM, modificar el atributo value en campos de formulario, etc.)
En el formulario que acompaña este artículo, hemos modificado el mensaje del botón de envío, y la leyenda de los campos agrupados con un fieldset. En el primer caso, al tratarse de una etiqueta "button", hemos reemplazado su primer y único nodo hijo que es solo texto, por un nuevo nodo también de texto con el nuevo contenido, mediante el método replaceChild(); para estos casos es más popular el uso de innerHTML, aunque no se considera DOM estándar. Si hubiera sido una etiqueta "input" podría cambiarse el atributo value de la misma. En el caso del "fieldset", hemos puesto dentro de la etiqueta "legend" tres elementos genéricos en línea "span", uno para cada idioma.
Puede verse como hemos terminado el diseño, con un juego de banderas y una combinación de colores que siempre se tratará de algo personal.
Como comentario adicional, podemos hacer lo mismo de forma más estructurada usando objetos, se podría declarar el objeto "formulario" de tal manera que para ocultar en un determinado idioma, todos sus ítems podríamos poner:
formulario[idioma].ocultar();
La declaración sería:
function objetoForm(cabecera, nombre, telefono, idiomas, es, en, fr, comentario, envio) { this.cabecera = cabecera; this.nombre = nombre; this.telefono = telefono; this.idiomas = idiomas; this.es = es; this.en = en; this.fr = fr; this.comentario = comentario; this.envio = document.createTextNode(envio); } // Nótese como se crea un nodo de texto en la inicialización del objeto. var formulario = new Array(); formulario["hispano"] = new objetoForm( "hispano", "es_nombre", "es_telefono", "es_idiomas", "es_es", "es_en", "es_fr", " Enviar formulario de contacto " ); // lo mismo para los demás idiomas.
Ahora definimos el método ocultar para los objetos "objetoForm":
objetoForm.prototype.ocultar = function() { document.getElementById(this.cabecera).style.display = "none"; document.getElementById(this.nombre).style.display = "none"; // así con el resto de los atributos... }
La forma de mostrar es análoga, pero debemos diferenciar los elementos de línea de los elementos de bloque y los elementos donde debe modificarse el contenido (no se me ocurren otros discriminantes, pero si los hubiese deberíamos considerarlos también). En este caso solo falta mostrar el reemplazo de contenidos del botón de envío:
with(document.getElementById("boton_form")) replaceChild(this.envio, firstChild); // this.envio había sido creado como nodo de texto
En definitiva, con los mismos botones, el método ponerIdioma se definiría de esta manera:
function ponerIdioma(cual) { formulario[idioma].ocultar() idioma = cual; formulario[idioma].mostrar() }
Se podría implementar el objeto de manera un poco más completa, añadiéndole información sobre los elementos en línea, en bloque, etc., aunque no tiene interés en este artículo
Aunque cada vez hay menos usuarios que deshabiliten javascript para navegar por Internet, siempre es recomendable que nuestras páginas sean accesibles, así que voy a plantear un simple truco que consigue ese objetivo con un lenguaje del servidor; en este caso con ayuda de php.
La dirección de nuestra página debe llevar un parámetro que nos servirá para discriminar los idiomas, por ejemplo: "pagina.php?idioma=hispano". Con php el valor del parámetro se obtiene sencillamente con la instrucción:
<? $idioma = $_GET["idioma"]; ?>
En principio no nos preocuparemos de controlar que se usen datos válidos y supondremos que sí. Ahora la inicialización de los estilos la condicionaremos al idioma actual:
#hispano { display: <?=($idioma == "hispano") ? "block" : "none"; ?>; } #english { display: <?=($idioma == "english") ? "block" : "none"; ?>; } #francoise { display: <?=($idioma == "francoise") ? "block" : "none"; ?>; }
El truco que comentábamos no es otro que envolver las imágenes que hemos usado como botones, con enlaces donde solo aparezca el parámetro del idioma y a la vez cancelar el enlace:
<a href="?idioma=english" onclick="return false" > <img src="pngurl.php?url=../dibujos/great_britain3.gif" alt="idioma" style="border: 2px outset #eeeeee; cursor: pointer" onclick="ponerIdioma('english')" /> </a>
Si está javascript deshabilitado, no se cancela el enlace y se enlaza a la página con el idioma seleccionado; y en el caso contrario se cancela el enlace y se ejecuta el script.
A continuación, algunos enlaces relacionados:
Las traducciones del formulario de ejemplo las he realizado con Google translate .