La función gettext() es la forma semi-oficial de manejar una localización y está muy bien integrado en los entornos del tipo Unix, lo cual es bueno y malo. Un grave problema es que depende del soporte de idioma que esté instalado en el servidor, lo cual puede hacer que una aplicación que funciona perfectamente en un servidor, no funcione en otro. Por otra parte, para su inicialización requiere una serie de llamadas a funciones que parecen un tanto caprichosas y que están pensadas más desde el punto de vista organizativo del servidor Unix que de la aplicación. Otros entornos, como Windows, esto puede representar un problema, por ejemplo, si se desarrolla en un ordenador Windows para usar en un servidor con Linux.

El ejemplo muestra cómo usar las funciones necesarias para gettext(). El fuente de la página muestra llamadas a las funciones setlocale(), bindtextdomain() y textdomain() las cuales deben estar al inicio de cualquier script, antes de la primer llamada a gettext() que, por otra parte, no verán en el fuente, dado que gettext() tiene predefinido como alias la función _(), que siendo mucho más breve, es más cómoda.

La explicación del manual sobre el uso de estas funciones es insuficiente y sin recorrer los comentarios de los usuarios, más abajo (que, además, no están traducidos) no es posible poner la cosa a funcionar.

La función setlocale() es la que establece el idioma que se utilizará, aunque en realidad hace mucho más que eso. Permite definir, por ejemplo, cómo se les dará formato a los números (el uso de comas y puntos para miles y decimales), moneda (símbolo monetario, cantidad de decimales, etc), fechas (orden de las partes) y varias otras cosas que se detallan en su documentación.

En el ejemplo usamos la constante LC_ALL para localizar todos los aspectos posibles. Aquí es donde reside el primer problema, el éxito de la función setlocale() depende de que la localización pedida exista en el servidor. Por ejemplo, un servidor puede tener instalado fr_FR (francés de Francia) pero no fr_BE (francés de Bélgica) o fr_CG (francés del Congo), puede tener ca_ES (catalán de España) pero no ca_FR (catalán de Francia). Uno podría querer obviar estos problemas simplemente indicando el código de idioma y no el de país, por ejemplo fr, es o ca, y dependiendo del servidor, estos pueden estar disponibles o no.

Por otra parte, el sitio en cuestión puede ser un sitio para un grupo de filólogos que estudian idiomas inusuales, tales como klingon, que tiene su código ISO-639 (tlh) o esperanto (epo). En el ejemplo se ha agregado una casilla donde ingresar un código de localización y ver el resultado donde dice `locale actual´. Si se muestra un resultado, el código indicado existe, sino, queda en blanco. La función setlocale() llama a la función equivalente del sistema operativo y retorna lo que esta le indica. Esto es importante pues es posible que la función devuelva algo, pero distinto de lo indicado. Por ejemplo, el sistema operativo es libre de indicar que no tiene `en_UK´ pero que si tiene `en´. Eso hace que uno no tenga más remedio que ponerse a explorar en el servidor para ver qué idiomas tiene y, según eso, ver qué ofrecer y, por encima de todo, cómo estructurar la aplicación, pues lo que todavía no hemos visto es dónde ubicar el archivo de traducciones.

Los argumentos de este trío de funciones son los que determinan la ubicación de los archivos de traducción, concretamente en el caso del ejemplo:


$locale = setlocale(LC_ALL, `en_US´);
bindtextdomain(`ejemplo´, `./locale´);
textdomain(`ejemplo´);

el archivo de traducciones se encontrará en:

./locale/en_US/LC_MESSAGES/ejemplo.mo

Dejo como ejercicio para el lector dilucidar de dónde sale cada segmento, aunque aclaro que LC_MESSAGES es fijo e inalterable como lo es la extensión .mo para el archivo. Esto hace evidente un problema, uno debe tener tantas carpetas con códigos de localización como vaya a ofrecer, aunque el contenido de es_AR sea idéntico al de es_UY, como en el caso del ejemplo donde usé en_US arbitrariamente en lugar de, por ejemplo, en_UK. La diferencia puede no ser importante en las traducciones, pero si en otros aspectos de la localización como el signo monetario $ ó �, o el orden de los elementos de la fecha.

Todo esto hace que esta solución no sea muy portable, y es de suponer que si uno está internacionalizando una aplicación en muchos casos es porque pretende hacerla portable. La dependencia de todo el paquete de gettext() de la configuración del servidor en que reside, hace que pueda ser un problema para quien debe instalar y mantener el paquete.

Finalmente, un `bug´ que seguramente se solucionará, eventualmente … La mayoría de las aplicaciones `internacionales´ se escriben en inglés por lo que los textos originales están en ese idioma. El ejemplo que acompaña este artículo está en castellano. Noten que si seleccionan como idioma el inglés, los textos donde el original contuviera acentos, eñe o cualquier otra letra o símbolo que no sea ASCII nativo, gettext() no encontrará la traducción, cosa que sí hará con cualquier texto donde el original sea puro ASCII, aunque el texto traducido sí contenga caracteres no-ASCII.

Por todo esto, en conclusión, no recomiendo usar las funciones de gettext() de PHP aunque, como alternativa, existe un paquete de PHP escrito en PHP mismo, que es mucho más simple de usar y más fácil de mantener. De hecho, es el que usa la aplicación WordPress con que funciona este mismo blog y que veremos en el siguiente artículo.

Viene de: Internacionalización y localización: usando arrays

Continúa en:Internacionalización y localización: usando PHP-gettext

Indice: Internacionalización y Localización: índice