Plataforma multi-idioma en PHP

Escrito en Tutoriales

Plataforma multi-idioma

Os voy a hablar de cómo hemos implementado en www.sortea2.com la plataforma multi-idioma, es un sistema bien simple, pero totalmente funcional.

Lo primero que debemos tener en cuenta es las cosas que necesitamos:

  1. Detectar el idioma del usuario para mostrarle el idioma que mejor le convenga.
  2. Tener los textos escritos en todos los idiomas que necesites utilizar.
  3. Darle la opción al usuario de que pueda cambiar de idioma en el momento en que quiera.


Detectar idioma del usuario

Para detectar el idioma del usuario, en www.sortea2.com decidimos detectar el idioma del navegador, porque era una de las maneras más simples y útiles. Para ello, con utilizar simplemente la siguiente variable de servidor ya podemos obtener el idioma del navegador.

$idioma = $_SERVER[‘HTTP_ACCEPT_LANGUAGE’];

El problema es que habitualmente, en casi todos los navegadores, lo que se nos devuelve por esa variable de servidor es el idioma y su derivación, algo del tipo: «es-es», a nosotros lo que nos interesa son únicamente las dos primeras letras, que son las que nos dicen el idioma propiamente dicho.

Para ello, podemos realizar un simple parseo de las dos primeras letras, tal y como se muestra a continuación:

$idioma = substr($idioma, 0, 2);

Bien, ahora tenemos en la variable $idioma una cadena que será algo así como «es» o «en». Ya hemos obtenido el idioma del navegador.


Tener los textos escritos en todos los idiomas que se necesiten

Hay varias opciones para tener los textos escritos en algún lugar para poder acceder a ellos dependiendo de qué idioma se necesite. Se podría hacer mediante base de datos o como nosotros optamos: con archivos de constantes de php. Este método es más eficiente que el de las conexiones a base de datos, porque optimiza los recursos del servidor y porque los archivos de constantes se guardan el la memoria del servidor y no hace falta estar llamandolos continuamente.

Hace falta tener tantos archivos de constantes como idiomas se desee poder utilizar. Estos archivos tienen que tener esta estructura:

Archivo es.php

<?php

define (SORTEOS_Y_APUESTAS_ENTRE_COLEGAS, «Sortea2 sorteos y apuestas entre colegas»);

define (VER_SORTEOS_PUBLICOS, «ver sorteos públicos»);

define (AVANZADOS, «sorteos avanzados»);

?>

Archivo en.php

<?php

define (SORTEOS_Y_APUESTAS_ENTRE_COLEGAS, «Sortea2: Raffles and betting with colleagues»);

define (VER_SORTEOS_PUBLICOS, «public raffles»);

define (AVANZADOS, «advanced raffles»);

?>

Hacer que se abra un archivo de idioma u otro dependiendo del navegador

Esta es la parte más simple. Lo único que hay que hacer es que si $idioma es «es», que se abra el archivo de idioma es.php, y si es «en», que se abra en.php

En nuestro caso, como nuestra página solo está disponible en español y en inglés, lo que hemos hecho es que si el idioma del navegador no es español, entonces que se abra el archivo de idiomas inglés. En caso de tener la necesidad de dividir los idiomas en varios archivos, porque se necesitan para lugares independientes, o por lo que sea, se puede pasar como parámetro opcional la variable $string, que se puede utilizar para usar archivos de idioma del tipo «es-sorteos.php» o «en-sorteos.php», si la variable está vacía, entonces se abrirá el archivo «es.php», lógicamente.

if ($idioma == «es»)

{

require_once(PHPPATH.«/langs/es».$string.«.php»);

}

else

{

require_once(PHPPATH.«/langs/en».$string.«.php»);

}

Todo se debería tener en una función en un archivo que se suela llamar en todas lás páginas de su web. Por ejemplo, una función que se llamase of_idioma() que devolviese la variable $idioma, por si se tiene que utilizar en algún momento, en alguna página de su web.

Método de utilizarlo

Una vez llamada la función of_idioma(), podemos llamar a los textos refiriéndose a ellos por medio del nombre de la constante. O osea, para escribir «Sortea2 – sorteos y apuestas entre colegas», en vez de escribir la frase directamente, hay que escribir la constante, que dependiendo del archivo de idioma que se haya abierto, tendrá un significado u otro.

of_idioma();

echo «Sortea2 – sorteos y apuestas entre colegas»;//No funcionaría

echo SORTEOS_Y_APUESTAS_ENTRE_COLEGAS; //Sí funcionaría


Resumen

Así, lo que hay que tener en cuenta es lo siguiente:

a) El idioma en principio lo capturamos del navegador.

b) En función del idioma, incluimos un fichero de constantes u otro. Si la página es muy extensa, podemos usar distintos ficheros de constantes y siempre haremos una de esas distinciones: si el idioma es español, carga las constantes en español, si es inglés, las constantes en inglés.

c) Para escribir los textos, usamos en lugar de literales los valores de las constantes. Como regla nemotécnica es bueno que los nombres de las constantes sean parecidos a los textos que representan.


Mejorando la experiencia del usuario. Cookie de idioma

Puede y suele ocurrir que el idioma del navegador no sea el que prefiera el usuario. Para ello en sortea2 incluimos al pie de todas las páginas un link para cambiar de idioma. Si la página está en español, el link dice «Read this web in English». Si está en inglés «Ver esta página en español».

Cuando un usuario realiza la selección de idioma, clickeando en dicho link, lo que hacemos es crear una cookie. Mediante dicha cookie que se guarda en el disco del ordenador del usuario que visita la página, almacenamos la preferencia de selección de idioma.

Por ello, en lugar de usar siempre el idioma del navegador hacemos lo siguiente:

a) Si el usuario tiene la cookie guardada, ese idioma prevalece.

b) De lo contrario, usamos el idioma del navegador.

Guardar la cookie es algo relativamente sencillo y de lo que pueden encontrarse numerosos ejemplos en la web. Como nosotros hemos empleado Jquery y el plugin de jquery.cookie, el código es peculiar aunque también ilustrativo:

$(document).ready(function(){

$(«a[name=’cooken’],a[name=’cookes’],a[name=’cookde’]»).
click(function(event)

{

var cookiename = ‘lan’;

var lang = $(this).attr(«name»);

language = lang.substr(lang.length -2, 2);

event.preventDefault();

cookieval = $.cookie(cookiename,language,{ expires: 7 , path: ‘/’});

window.location.href=window.location.href;

});

});

Con este código, cuando se pulsa uno de los links de idioma, primero impedimos que se desplace a la ruta que indica ese link (preventdefault).

Luego seleccionamos las últimas letras del nombre de dicho link, nos servirán para determinar el idioma a guardar. Observar que el ejemplo también está preparado para el idioma «de», por si queremos traducirla al alemán.

Con esas dos letras, generamos una cookie, que se llama «lan» y durará 7 días.

Y tras realizar todo esto, recargamos la ventana. Esta vez tendremos la cookie ya guardada y al recargarse lo reconoceremos y lo haremos en el idioma del usuario. Y como la cookie permanece en el sistema, su selección de idioma permanecerá.


Determinando el valor de la cookie

Ya hemos recorrido todo el camino. Ahora basta con juntar las piezas. El proceso es muy sencillo.

1. Cargamos la página.

2. ¿Tenemos cookie? Si es así, tomamos el idioma.

3. Si no hay cookie, tomamos el idioma del navegador.

4. Con ese valor de idioma cargamos un fichero de constantes u otro.

5. Nos referimos siempre a los literales con valores de constantes.

El código final es realmente simple:

$idioma = isset($_COOKIE[‘lan’]) ? $_COOKIE[‘lan’] : «»;

if ($idioma == «»)

{

$idioma = $_SERVER[‘HTTP_ACCEPT_LANGUAGE’];

$idioma = substr($idioma, 0, 2);
}

if ($idioma == «es»)

{

require_once(PHPPATH.«/langs/es».$string.«.php»);

}

elseif ($idioma == «en»)

{

require_once(PHPPATH.«/langs/en».$string.«.php»);

}

¿Algo no te ha quedado claro? Pregúntanoslo en los comentarios y te trataremos de ayudar.


Escrito por .

Escribe un comentario:



36 comentarios for “Plataforma multi-idioma en PHP”

  1. iim.vxk dice:

    gracias,,, pero aún no he resuelto el dilema – mediante una metodología ‘estándar’ – de los textos «dinámicos», esos adefesios donde x parte varia su valor, p. ej. obteniéndolo de una variable

    something like «welcome %user»…

    como le harán los grandes como WordPress y asi…

    investigando..

  2. bernabe dice:

    Puedes hacer algo así:

    define (WELCOME, «Welcome»);

    echo WELCOME . » «. $usuario;

    Es fácil, solo bastaría con concatenar cadenas. De hecho, en algunos sitios lo hemos tenido que utilizar así.

  3. Carlos dice:

    Bueno está super PERO PARA ELEMENTOS SWF COMO HAGO :| AHHH

  4. bernabe dice:

    Respuesta a Carlos:

    No sabría hacerlo para flash, pero podrías hacer dos animaciones swf, una en inglés y otra en español.

    Luego pones:

    $idioma = of_idioma();

    if ($idioma == «es»)
    {
    echo «< object >FLASH EN ESPAÑOL< / object >«;
    }
    else
    {
    echo «< object >FLASH EN INGLÉS< / object >«;
    }

    Así podría funcionar, se abriría una animación u otra dependiendo del idioma.

  5. Christian dice:

    Gracias Bernabe !

    Estoy probando el ejemplo que respondiste para Carlos de usar dos animaciones en flash, una ingles y otra en castellano, pero me no esta funcionando.

    Seguramente este haciendo las cosas mal…

    Paso a explicarte lo que hice :

    Lo que hice fue un archivo «index.php» y ahi puse el siguiente codigo :

    <?php

    $idioma = $_SERVER[‘HTTP_ACCEPT_LANGUAGE’];
    $idioma = substr($idioma, 0, 2);
    $idioma = of_idioma();

    if ($idioma == “es”)
    {
    echo “main2.swf“;
    }
    else
    {
    echo “main-eng2.swf“;
    }

    ?>

    Luego en el mismo directorio puse los dos .swf,

    Tengo que agregar algun otro archivo ? o algun .html ?

    Podrias escribirme el codigo completo que tengo que usar en el archivo .php ?

    Muchas Gracias :)

  6. bernabe dice:

    Christian, no lo has hecho del todo bien, el proceso sería el siguiente:

    $idioma = $_SERVER[‘HTTP_ACCEPT_LANGUAGE’];
    $idioma = substr($idioma, 0, 2);

    if ($idioma == “es”)
    {
    echo “/*OBJETO FLASH EN ESPAÑOL*/“;
    }
    else
    {
    echo “/*OBJETO FLASH EN INGLES*/“;
    }

    ?>

    De esa manera tendríamos el idioma en la variable $idioma, sin necesidad de tener que llamar a la función, porque el trabajo ya lo hacemos directamente.

    Después, para llamar al objeto en flash, no se utiliza el método que tú pones, el de poner directamente la ruta. Lo que hay que hacer es escribir el código HTML que hace que se muestre ese Flash. Sería una cosa como esta:


    <object classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0' width='199' height='100'>
    <param name='movie' value='AQUI VA LA RUTA'><param name='quality' value='high'>
    <param name='LOOP' value='false'>
    <embed src='AQUI VA LA RUTA' width='199' height='100' loop='false' quality='high' pluginspage='http://www.macromedia.com/go/getflashplayer' type='application/x-shockwave-flash'>
    </embed>
    </object>

    Donde pone AQUI VA LA RUTA, pones la ruta del archivo a abrir, y donde pone width=199′ height=’100′ puedes personalizarlo para que sea del tamaño de tu animación.

    Entonces, en vez de hacer echo «loquesea.swf»;, habría que hacer un echo de todo ese código que te he puesto.

    Espero haberte ayudado.

    Si tienes la más mínima duda, no dudes en volver a escribir un comentario que te lo responderé a la mayor brevedad posible.

  7. Carlos Avila dice:

    Discilpen chicos pero tengo un problema, estoy utlizando el metodo de la cookie, pero hay un inconveniente si end eterminado momento el usuario desea cambiar el idioma de la cookie, como lo haria?….como hago para que por ejemplo en la pagina español.php que me carga predeterminado por escogerla, cambie a ingles.php? si alguien sabe como ayudarme, escriba un correo a Pallosforever@hotmail.com gracias

  8. bernabe dice:

    Para eso lo que hacemos nosotros es usar jQuery, tienes que poner un link que diga el cambio de idioma que quieres hacer y añadirle un evento de javascript. En el evento se crea una cookie de idioma y se actualiza la página para que se vea el nuevo idioma.

    Con el código que se explica en la entrada se puede hacer toda la estructura perfectamente.

  9. Carlos Avila dice:

    Gracias por tu respuesta, funciona muy bien el unico porblema es que no necesito que lo seleccione segun el idioma del navegador, sino que una vez que el usuario lo seleccione recuerde siempre la ultima seleccion, por ejemplo tengo 2 pagimas una de español y otra de ingles…y si el usuario selecciona ingles recuerde siempre ingles hasta que lo cambie a español y viceversa, te agradeceria si me pudieras ayudar con este dilema Gracias de antemano

  10. bernabe dice:

    Entonces tienes que poner simplemente la parte de jQuery y quitar en la función de PHP la parte que hace que se obtenga el idioma del navegador.

    Sería adaptarlo de tal manera que solo leyera la cookie, que ignorara lo demás.

    Estas lineas irian fuera:

    if ($idioma == “”)

    {

    $idioma = $_SERVER[‘HTTP_ACCEPT_LANGUAGE’];

    $idioma = substr($idioma, 0, 2);
    }

  11. Carlos Avila dice:

    Muchas gracias ya resolvi el problema muy buena la explicacion ¿tienes mas tutoriales?, soy nuevo en esto de php, y estoy muy interezado en diversos temas.

    gracias nuevamente

  12. bernabe dice:

    Me alegro enormemente de haberte ayudado, Carlos.

    En esta dirección: http://www.sortea2.com/blog/category/tutoriales/ puedes ver todos los tutoriales que hemos escrito. Hemos escrito algunos interesantes como el de las Zonas horarias y PHP, otros de posicionamiento web, etc. etc.

    Y recuerda que si algún dia tienes que hacer un sorteo aleatorio o un amigo invisible, puedes hacerlo fácilmente con nuestra página.

    Saludos.

  13. carlos avila dice:

    holaaa, necesito ayuda, mira me encuentro manejando un JS …este JS escribe una cookie de y me envia a otra pagina…el problema viene cuando la quiero eliminar, esta en la raiz del sistema y no se como llamarla aqui un ejemplo:

    function cambiarIdioma(){

    document.cookie=»idioma=; path=/»esta parte es donde debe ir la ruta de la raiz…»/;expires=Monday, 19-Aug-1996 05:00:00 GMT»;
    document.location.href = ‘http://localhost:8080/index.php’;
    }

    y no se como hacerlo te agradeceria mucho si me ayudaras

  14. bernabe dice:

    Pues en path lo que tienes que poner son simplemente dos puntos y la barra:

    path=".."

    Los dos puntos indican que es la carpeta superior. Si no se añade nada más, entonces significa que es la página principal.

    Me parece que es eso. De todas maneras no haría falta borrar la cookie, con sobreescribirla con el nuevo idioma debería valer.

  15. carlos avila dice:

    hola, mira le he hecho como me dices pero no ha funcionado, puedes decirme como puedo sobreescribir el valor??

    gracias y disculpa las molestias

  16. carlos avila dice:

    disculpa si funciona…pero no en mozilla :S ….sabes como llego a la ruta superior especificando a mozilla???

  17. bernabe dice:

    Pues prueba poniendo una barra solamente /.

    Si te da más problemas, entonces pon la ruta absoluta y así te quitas de seguir pensando cosas. Eso es lo que yo haría.

  18. PsiGuia dice:

    Continuando con el primer comentario hecho en este post por iim.vxk, no queda resuelto el dilema de los textos “dinámicos”, y la solución expuesta no es suficientemente valida, ya que en el ejemplo que se ha puesto utilizar:
    define (WELCOME, “Welcome”);
    echo WELCOME . ” “. $usuario;

    no cubre la gran cantidad de casos en los que el orden de las palabras es diferente segun el idioma.
    Por ejemplo, si se quiere tener un literal donde cambie un numero:
    en castellano -> define (APTO, “apartamentos de 5 habitaciones”);
    en ingles -> define (APTO, “5 rooms apartments”);

    La solucion seria poner algo asi como
    en castellano -> define (APTO, “apartamentos de %1 habitaciones”);
    en ingles -> define (APTO, “%1 rooms apartments”);

    y luego, al recuperar el literal, pasarle el parámetro con el numero de habitaciones…

    Pero… ¿esto se puede conseguir de alguna manera? ¿Como seria?

    Muchas gracias.

  19. mateo dice:

    muchas gracias, no sabias cuanto tiempo busque algo asi grax

  20. Sandra dice:

    Para PsiGuia, el paso dinámico de parámetro sería:

    En castellano

    En inglés:

  21. Sandra dice:

    Para PsiGuia, el paso dinámico de parámetro sería:
    En castellano:
    define (APTO, «apartamentos de %s habitaciones»);
    En inglés:
    define (APTO, “%s rooms apartments”);

    printf(APTO,5);

    ó puedes usar también sprintf(APTO,5), checa que sustituí tu %1 por %s, en este caso.

  22. Pedro dice:

    Buenas tardes estoy intenta que me salga el multi idioma, peor no hay manera,

  23. carlos dice:

    Hola, estoy intentando implementar la parte del enlace para cambiar el idioma y no se como hacéis para que el atributo name tenga el valor de idioma contrario del predeterminado para que cambie.
    gracias anticipadas
    carlos

  24. bernabe dice:

    Cogiendo el valor de la cookie, carlos.

  25. carlos dice:

    perdona pero mi nivel de php es básico, no se con que variable, he probado varias pero no me ha funcionado, imagino que debe ser algo así

    name=»»

    saludos

  26. bernabe dice:

    mas bien sería name=’$idioma’

  27. carlos dice:

    Hola si perdona pero no me salió el código dentro de los paréntesis en el post anterior

    Así es como lo hice y el resultado es cookes el idioma activo en ese momento, pero al hacer click no cambia los textos. Hay que configurar algo en el jquery.cookie?

    Creo que el problema proviene de que las variables de idioma las cargo arriba del todo de la página y por tanto ocurre antes que de leer los javascripts y por eso no hace nada…es posible?
    saludos y gracias

  28. bernabe dice:

    Estaría bien que la variable se cargara después de haber mirado si en la cookie había ya algo, para en ese caso, coger lo que haya en la cookie.

  29. carlos carrera dice:

    Hola Bernabe, pues no se que se me escapa.
    He hecho comprobaciones en el navegador y la cookie se carga sin problemas. pero sigue sin cambiarme los textos.

    Pongamos como ejemplo la página de http://www.sortea2.com
    Si yo cargo la página en español y luego miro el valor del atributo name aparece name=»cooken» y si hago clic en el enlace se recarga la página, aparece en ingles y en enlace cambia a name=»cookes» correcto?

    Pues a mi si caso si la página esta en español y miro el atributo name me aparece name=»cookes» (no cooken como debería)

    el atributo name lo construyo así name=»cook<php echo $idioma; ?>

    …o debo crear un condicional para que si la página esta en español me cree un enlace con «cooken» y si la página en ingles me cree un enlace con «cookes»?
    saludos

  30. bernabe dice:

    Es ese el problema, lo que pasa es que el idioma que tienes que poner es el contrario al actual, por lo que si lo haces como tú dices, entonces siempre se quedará todo en español.

    Hazlo con un if mejor.

  31. carlos carrera dice:

    gracias con el if perfecto.

    Por cierto ya que estamos, para hacer una URL distinta para inglés tipo http://www.midominio.com/en/index.php para las estadisticas por ejemplo, se podría con este sistema?
    saludos

  32. bernabe dice:

    Poderse se podría, pero tendrías que hacer una redirección de tal manera que se envíe por GET el parámetro de $idioma y también hacer que ese parámetro prevalezca por delante de la cookie o del navegador del usuario.

  33. […] most easy to setup is probably to have tens or hundreds of PHP constants or an array with all the phrases and choose which array or which source code with constants apply […]

  34. David dice:

    Hola!

    Mis conocimientos de programación se reducen a php y tengo problemas con la parte de los enlaces para crear la cookie con el jquery.

    He descargado e incluido en mi poryecto jquery y el pulgin

    echo «»;
    echo «»;

    He incluido esto en la parte html del header

    Mi pregunta es, donde se debe localizar el fragmento de código para crear la cookie que se muestra en la entrada del blog.

    «$(document).ready(function(){
    $(“a[name=’cooken’],a[name=’cookes’],a[name=’cookde’]“).
    click(function(event)
    {
    var cookiename = ‘lan’;
    var lang = $(this).attr(“name”);
    language = lang.substr(lang.length -2, 2);
    event.preventDefault();
    cookieval = $.cookie(cookiename,language,{ expires: 7 , path: ‘/’});
    window.location.href=window.location.href;
    });
    });»

    Debería ir entre las etiquetas html ??
    Debe situarse en algún lugar especial?

    Y por ultimo, si deseo tener dos enlaces, uno que almacene la cookie que el idioma es español y otro que ingles, ¿cual seria la sintaxis?
    ¿Sería un enlace que no lleva a ninguna parte o que lleve a la dirección de la pagina actual?

    Gracias de antemano por la ayuda ;)

  35. Marcos dice:

    Muchas gracias, andaba buscando por todos lados como usar DEFINE para hacer una web multi-idioma. Saludos!

    DEFINE(GRACIAS, ‘Muchas gracias por el aporte’);
    echo GRACIAS;

  36. raquel dice:

    hola alguien me puede ayudar a poner un traslate en un apaginas web pero que no sea de google poque solo ese he encontrado que alguien me ayude graciasssss