{"id":66,"date":"2008-11-17T17:16:59","date_gmt":"2008-11-17T16:16:59","guid":{"rendered":"http:\/\/www.sortea2.com\/blog\/?p=66"},"modified":"2008-12-17T13:00:32","modified_gmt":"2008-12-17T12:00:32","slug":"plataforma-multi-idioma-parte-1","status":"publish","type":"post","link":"https:\/\/www.sortea2.com\/blog\/2008\/11\/plataforma-multi-idioma-parte-1\/","title":{"rendered":"Plataforma multi-idioma en PHP"},"content":{"rendered":"<h2>Plataforma multi-idioma<\/h2>\n<p>Os voy a hablar de c\u00f3mo hemos implementado en <a href=\"http:\/\/www.sortea2.com\">www.sortea2.com<\/a> la plataforma multi-idioma, es un sistema bien simple, pero totalmente funcional.<\/p>\n<p>Lo primero que debemos tener en cuenta es las cosas que necesitamos:<\/p>\n<ol>\n<li>Detectar el idioma del usuario para mostrarle el idioma que mejor le convenga.<\/li>\n<li>Tener los textos escritos en todos los idiomas que necesites utilizar.<\/li>\n<li>Darle la opci\u00f3n al usuario de que pueda cambiar de idioma en el momento en que quiera.<\/li>\n<\/ol>\n<p><span class=\"header\"><br \/>\nDetectar idioma del usuario<\/span><\/p>\n<p>Para detectar el idioma del usuario, en <a href=\"http:\/\/www.sortea2.com\">www.sortea2.com<\/a> decidimos detectar el idioma del navegador, porque era una de las maneras m\u00e1s simples y \u00fatiles. Para ello, con utilizar simplemente la siguiente variable de servidor ya podemos obtener el idioma del navegador.<\/p>\n<div id=\"codigo\">$idioma = <span class=\"vb_server\">$_SERVER<\/span>[<span class=\"literales\">&#8216;HTTP_ACCEPT_LANGUAGE&#8217;<\/span>];<\/div>\n<p>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\u00f3n, algo del tipo: \u00abes-es\u00bb, a nosotros lo que nos interesa son \u00fanicamente las dos primeras letras, que son las que nos dicen el idioma propiamente dicho.<\/p>\n<p>Para ello, podemos realizar un simple parseo de las dos primeras letras, tal y como se muestra a continuaci\u00f3n:<\/p>\n<div id=\"codigo\">$idioma = <span class=\"funciones_php\">substr<\/span>($idioma, <span class=\"numero\">0<\/span>, <span class=\"numero\">2<\/span>);<\/div>\n<p>Bien, ahora tenemos en la variable $idioma una cadena que ser\u00e1 algo as\u00ed como \u00abes\u00bb o \u00aben\u00bb. Ya hemos obtenido el idioma del navegador.<\/p>\n<p><span class=\"header\"><br \/>\nTener los textos escritos en todos los idiomas que se necesiten<\/span><\/p>\n<p>Hay varias opciones para tener los textos escritos en alg\u00fan lugar para poder acceder a ellos dependiendo de qu\u00e9 idioma se necesite. Se podr\u00eda hacer mediante base de datos o como nosotros optamos: con <b>archivos de constantes de php<\/b>. Este m\u00e9todo es m\u00e1s 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.<\/p>\n<p>Hace falta tener tantos archivos de constantes como idiomas se desee poder utilizar. Estos archivos tienen que tener esta estructura:<\/p>\n<h4>Archivo es.php<\/h4>\n<div id=\"codigo\"><span class=\"php\">&lt;?php<\/span><\/p>\n<p><span class=\"funciones_php\">define<\/span> <span class=\"punto\">(<\/span>SORTEOS_Y_APUESTAS_ENTRE_COLEGAS, <span class=\"literales\">\u00abSortea2 sorteos y apuestas entre colegas\u00bb<\/span><span class=\"punto\">)<\/span>;<\/p>\n<p><span class=\"funciones_php\">define<\/span> <span class=\"punto\">(<\/span>VER_SORTEOS_PUBLICOS, <span class=\"literales\">\u00abver sorteos p\u00fablicos\u00bb<\/span><span class=\"punto\">)<\/span>;<\/p>\n<p><span class=\"funciones_php\">define<\/span> <span class=\"punto\">(<\/span>AVANZADOS, <span class=\"literales\">\u00absorteos avanzados\u00bb<\/span><span class=\"punto\">)<\/span>;<\/p>\n<p><span class=\"php\">?&gt;<\/span><\/div>\n<h4>Archivo en.php<\/h4>\n<div id=\"codigo\"><span class=\"php\">&lt;?php<\/span><\/p>\n<p><span class=\"funciones_php\">define<\/span> <span class=\"punto\">(<\/span>SORTEOS_Y_APUESTAS_ENTRE_COLEGAS, <span class=\"literales\">\u00abSortea2: Raffles and betting with colleagues\u00bb<\/span><span class=\"punto\">)<\/span>;<\/p>\n<p><span class=\"funciones_php\">define<\/span> <span class=\"punto\">(<\/span>VER_SORTEOS_PUBLICOS, <span class=\"literales\">\u00abpublic raffles\u00bb<\/span><span class=\"punto\">)<\/span>;<\/p>\n<p><span class=\"funciones_php\">define<\/span> <span class=\"punto\">(<\/span>AVANZADOS, <span class=\"literales\">\u00abadvanced raffles\u00bb<\/span><span class=\"punto\">)<\/span>;<\/p>\n<p><span class=\"php\">?&gt;<\/span><\/div>\n<p>Hacer que se abra un archivo de idioma u otro dependiendo del navegador<\/p>\n<p>Esta es la parte m\u00e1s simple. Lo \u00fanico que hay que hacer es que si $idioma es \u00abes\u00bb, que se abra el archivo de idioma es.php, y si es \u00aben\u00bb, que se abra en.php<\/p>\n<p>En nuestro caso, como nuestra p\u00e1gina solo est\u00e1 disponible en espa\u00f1ol y en ingl\u00e9s, lo que hemos hecho es que si el idioma del navegador no es espa\u00f1ol, entonces que se abra el archivo de idiomas ingl\u00e9s. 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\u00e1metro opcional la variable $string, que se puede utilizar para usar archivos de idioma del tipo \u00abes-sorteos.php\u00bb o \u00aben-sorteos.php\u00bb, si la variable est\u00e1 vac\u00eda, entonces se abrir\u00e1 el archivo \u00abes.php\u00bb, l\u00f3gicamente.<\/p>\n<div id=\"codigo\"><span class=\"verde\">if<\/span> ($idioma == <span class=\"literales\">\u00abes\u00bb<\/span>)<\/p>\n<p>{<\/p>\n<p><span class=\"indented\"><span class=\"verde\">require_once<\/span>(PHPPATH<\/span><span class=\"punto\">.<\/span><span class=\"literales\">\u00ab\/langs\/es\u00bb<\/span><span class=\"punto\">.<\/span>$string<span class=\"punto\">.<\/span><span class=\"literales\">\u00ab.php\u00bb<\/span>);<\/p>\n<p>}<\/p>\n<p><span class=\"verde\">else<\/span><\/p>\n<p>{<\/p>\n<p><span class=\"indented\"><span class=\"verde\">require_once<\/span>(PHPPATH<\/span><span class=\"punto\">.<\/span><span class=\"literales\">\u00ab\/langs\/en\u00bb<\/span><span class=\"punto\">.<\/span>$string<span class=\"punto\">.<\/span><span class=\"literales\">\u00ab.php\u00bb<\/span>);<\/p>\n<p>}<\/p><\/div>\n<p>Todo se deber\u00eda tener en una funci\u00f3n en un archivo que se suela llamar en todas l\u00e1s p\u00e1ginas de su web. Por ejemplo, una funci\u00f3n que se llamase of_idioma() que devolviese la variable $idioma, por si se tiene que utilizar en alg\u00fan momento, en alguna p\u00e1gina de su web.<\/p>\n<h4>M\u00e9todo de utilizarlo<\/h4>\n<p>Una vez llamada la funci\u00f3n of_idioma(),  podemos llamar a los textos refiri\u00e9ndose a ellos por medio del nombre de la constante. O osea, para escribir \u00abSortea2 &#8211; sorteos y apuestas entre colegas\u00bb, en vez de escribir la frase directamente, hay que escribir la constante, que dependiendo del archivo de idioma que se haya abierto, tendr\u00e1 un significado u otro.<\/p>\n<div id=\"codigo\">of_idioma();<\/p>\n<p><span class=\"funciones_php\"> echo<span class=\"literales\"> \u00abSortea2 &#8211; sorteos y apuestas entre colegas\u00bb<\/span>;<span class=\"comentario\">\/\/No funcionar\u00eda<\/span><\/span><\/p>\n<p><span class=\"funciones_php\">echo<\/span> <span style=\"color: black;\">SORTEOS_Y_APUESTAS_ENTRE_COLEGAS;<\/span> <span class=\"comentario\">\/\/S\u00ed funcionar\u00eda<\/span><\/div>\n<p><span class=\"header\"><br \/>\nResumen<\/span><\/p>\n<p>As\u00ed, lo que hay que tener en cuenta es lo siguiente:<\/p>\n<p>a) El idioma en principio lo capturamos del navegador.<\/p>\n<p>b) En funci\u00f3n del idioma, incluimos un fichero de constantes u otro. Si la p\u00e1gina es muy extensa, podemos usar distintos ficheros de constantes y siempre haremos una de esas distinciones: si el idioma es espa\u00f1ol, carga las constantes en espa\u00f1ol, si es ingl\u00e9s, las constantes en ingl\u00e9s.<\/p>\n<p>c) Para escribir los textos, usamos en lugar de literales los valores de las constantes. Como regla nemot\u00e9cnica es bueno que los nombres de las constantes sean parecidos a los textos que representan.<\/p>\n<p><span class=\"header\"><br \/>\nMejorando la experiencia del usuario. Cookie de idioma<\/span><\/p>\n<p>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\u00e1ginas un link para cambiar de idioma. Si la p\u00e1gina est\u00e1 en espa\u00f1ol, el link dice \u00abRead this web in English\u00bb. Si est\u00e1 en ingl\u00e9s \u00abVer esta p\u00e1gina en espa\u00f1ol\u00bb.<\/p>\n<p>Cuando un usuario realiza la selecci\u00f3n 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\u00e1gina, almacenamos la preferencia de selecci\u00f3n de idioma.<\/p>\n<p>Por ello, en lugar de usar siempre el idioma del navegador hacemos lo siguiente:<\/p>\n<p>a) Si el usuario tiene la cookie guardada, ese idioma prevalece.<\/p>\n<p>b) De lo contrario, usamos el idioma del navegador.<\/p>\n<p>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\u00f3digo es peculiar aunque tambi\u00e9n ilustrativo:<\/p>\n<div id=\"codigo\">$(document).ready(function(){<\/p>\n<p>$(\u00aba[name=&#8217;cooken&#8217;],a[name=&#8217;cookes&#8217;],a[name=&#8217;cookde&#8217;]\u00bb).<br \/>\nclick(function(event)<\/p>\n<p>{<\/p>\n<p>var cookiename = &#8216;lan&#8217;;<\/p>\n<p>var lang = $(this).attr(\u00abname\u00bb);<\/p>\n<p>language = lang.substr(lang.length -2, 2);<\/p>\n<p>event.preventDefault();<\/p>\n<p>cookieval = $.cookie(cookiename,language,{ expires: 7 , path: &#8216;\/&#8217;});<\/p>\n<p>window.location.href=window.location.href;<\/p>\n<p>});<\/p>\n<p>});<\/p><\/div>\n<p>Con este c\u00f3digo, cuando se pulsa uno de los links de idioma, primero impedimos que se desplace a la ruta que indica ese link (preventdefault).<\/p>\n<p>Luego seleccionamos las \u00faltimas letras del nombre de dicho link, nos servir\u00e1n para determinar el idioma a guardar. Observar que el ejemplo tambi\u00e9n est\u00e1 preparado para el idioma \u00abde\u00bb, por si queremos traducirla al alem\u00e1n.<\/p>\n<p>Con esas dos letras, generamos una cookie, que se llama \u00ab<strong>lan<\/strong>\u00bb y durar\u00e1 7 d\u00edas.<\/p>\n<p>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\u00f3n de idioma permanecer\u00e1.<\/p>\n<p><span class=\"header\"><br \/>\nDeterminando el valor de la cookie<\/span><\/p>\n<p>Ya hemos recorrido todo el camino. Ahora basta con juntar las piezas. El proceso es muy sencillo.<\/p>\n<p>1. Cargamos la p\u00e1gina.<\/p>\n<p>2. \u00bfTenemos cookie? Si es as\u00ed, tomamos el idioma.<\/p>\n<p>3. Si no hay cookie, tomamos el idioma del navegador.<\/p>\n<p>4. Con ese valor de idioma cargamos un fichero de constantes u otro.<\/p>\n<p>5. Nos referimos siempre a los literales con valores de constantes.<\/p>\n<p>El c\u00f3digo final es realmente simple:<\/p>\n<div id=\"codigo\">$idioma = isset(<span class=\"vb_server\">$_COOKIE<\/span>[<span class=\"literales\">&#8216;lan&#8217;<\/span>]) <span class=\"punto\">?<\/span> <span class=\"vb_server\">$_COOKIE<\/span>[<span class=\"literales\">&#8216;lan&#8217;<\/span>] <span class=\"punto\">:<\/span> <span class=\"literales\">\u00ab\u00bb<\/span>;<\/p>\n<p><span class=\"verde\">if<\/span> ($idioma <span class=\"punto\">==<\/span> <span class=\"literales\">\u00ab\u00bb<\/span>)<\/p>\n<p>{<\/p>\n<p><span class=\"indented\"> $idioma = <span class=\"vb_server\">$_SERVER<\/span>[<span class=\"literales\">&#8216;HTTP_ACCEPT_LANGUAGE&#8217;<\/span>];<br \/>\n<\/span><br \/>\n<span class=\"indented\"> $idioma = <span class=\"funciones_php\">substr<\/span>($idioma, <span class=\"numero\">0<\/span>, <span class=\"numero\">2<\/span>);<\/span><br \/>\n}<\/p>\n<p><span class=\"verde\">if<\/span> ($idioma == <span class=\"literales\">\u00abes\u00bb<\/span>)<\/p>\n<p>{<\/p>\n<p><span class=\"indented\"><span class=\"verde\">require_once<\/span>(PHPPATH<span class=\"punto\">.<\/span><span class=\"literales\">\u00ab\/langs\/es\u00bb<\/span><span class=\"punto\">.<\/span>$string<span class=\"punto\">.<\/span><span class=\"literales\">\u00ab.php\u00bb<\/span>);<br \/>\n<\/span><br \/>\n}<\/p>\n<p><span class=\"verde\">elseif<\/span> ($idioma == <span class=\"literales\">\u00aben\u00bb<\/span>)<\/p>\n<p>{<\/p>\n<p><span class=\"indented\"><span class=\"verde\">require_once<\/span>(PHPPATH.<span class=\"literales\">\u00ab\/langs\/en\u00bb<\/span>.$string.<span class=\"literales\">\u00ab.php\u00bb<\/span>);<\/span><\/p>\n<p>}<\/p><\/div>\n<p>\u00bfAlgo no te ha quedado claro? Preg\u00fantanoslo en los comentarios y te trataremos de ayudar.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Plataforma multi-idioma Os voy a hablar de c\u00f3mo 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: Detectar el idioma del usuario para mostrarle el idioma que mejor le convenga. Tener los textos escritos en todos los [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-66","post","type-post","status-publish","format-standard","hentry","category-tutoriales"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.sortea2.com\/blog\/wp-json\/wp\/v2\/posts\/66","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sortea2.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sortea2.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sortea2.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sortea2.com\/blog\/wp-json\/wp\/v2\/comments?post=66"}],"version-history":[{"count":21,"href":"https:\/\/www.sortea2.com\/blog\/wp-json\/wp\/v2\/posts\/66\/revisions"}],"predecessor-version":[{"id":68,"href":"https:\/\/www.sortea2.com\/blog\/wp-json\/wp\/v2\/posts\/66\/revisions\/68"}],"wp:attachment":[{"href":"https:\/\/www.sortea2.com\/blog\/wp-json\/wp\/v2\/media?parent=66"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sortea2.com\/blog\/wp-json\/wp\/v2\/categories?post=66"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sortea2.com\/blog\/wp-json\/wp\/v2\/tags?post=66"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}