Páginas multilenguaje con javascript

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.

Selección sencilla

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).

Array de etiquetas asociativo por idiomas

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.

Cambios de contenidos

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.


idioma idioma idioma Formulario de Contacto

idioma idioma idioma Contact Form

idioma idioma idioma Forme de Contact

Idiomas que conoces Languages that you know Langues que vous savez

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.

Usando objetos

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

Unos retoques y es accesible

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.

Para terminar

A continuación, algunos enlaces relacionados:

Las traducciones del formulario de ejemplo las he realizado con Google translate .





Comentarios

Nombre: Giovanni Alfredo Garciliano Diaz
Procedencia: Villahermosa, Tabasco, Mexico
E-Mail: xivanni@hotmail.com
URL: http://giobeatle1794.esy.es
Fecha de envío: 1 de septiembre de 2016, a las 03:12.
Valoración:
comentario:

Me parece buena la solución, excepto por que hay gente que navega desde navegadores sin soporte para JavaScript (no necesariamente obsoletos, por ejemplo, los navegadores para consola), o gente que no quiere activar JavaScript, ellos verían los textos de todos los idiomas

Por otro lado, Google no sabe interpretar código JavaScript, e indexaría la página completa con todos los idiomas.

Y también afecta a la semántica de la página. Pero por todo esto, me parece muy buena la solución.


Nombre: Ignacio
Procedencia: Alicante
E-Mail: khayyn1@gmail.com
URL: http://www.webhosint.com
Fecha de envío: 21 de mayo de 2013, a las 17:56.
Valoración:
comentario:

Hola buenas. Estoy intentando usar la primera parte del código, sin el formulario.
¿Como hago para que al cargar la web no me cargue los 2 idiomas? Es decir, carga uno seguido del otro, luego le das a la banderita y si que sale sólo en un idioma. ¿Se podría hacer que por defecto sólo saliese en un idioma y al pulsar en la bandera de otro se cambiase?


Nombre: Herol Arana
Procedencia: Madrid
E-Mail: herol_ac14@hotmail.com
URL: http://oceandesdunes.iespana.es
Fecha de envío: 2 de octubre de 2009, a las 02:11.
comentario:

Hola, me gustaria saber como hago para hacerla en ingles y frances no lo entendi tan bién el tutorial en eso de poneridioma (cual) es alli donde me perdi, me aclaraias un poco el tema si es mi e-mail seria genial. Tengo ademas las figuritas de banderas para los idiomas y como poder enlazarlas con su respectivo html o seria css , o con q lo hago. Gracias gracias gracias.


Colabore enviando su comentario

Nombre
Procedencia
Página web
E-mail *
Evaluación evaluarevaluarevaluarevaluarevaluarevaluarevaluarevaluarevaluarevaluar
Código de envío

Rellene este campo con la clave de la imagen: codigo de envío

Nota Importante

El campo E-Mail es obligatorio para activar por correo electrónico el comentario (si no desea que se haga público, marque la casilla "anonimato"). También es obligatorio el código "captcha" (el número que se ve en la imagen adjunta); y por supuesto, debe existir un comentario.

Puede encontrar información sobre este sistema de comentarios en este enlace: Ponga comentarios en su web.

Edición negrita cursiva subrayado   alineación izquierda alineación derecha alineación centrada alineación justificada   Insertar enlace insertar imagen   Emoticones: [:)] [:(] [:x] [BIEN] [MAL] [SI] [NO] [APLAUSOS] [MEJORABLE] [¡A VER!] [¡DÉJAME PENSAR!] [FLIPE] [¡SIN PALABRAS!]
Copyright © 2006-2018 www.caricatos.net
Visitas: 58053