lunes, 2 de febrero de 2015

Cómo conseguir que gettext funcione en php

A menudo necesitamos internacionalizar los programas que desarrollamos en PHP.

En mi libro Programación profesional en PHP con Slim, París y Twig trato este tema en el capítulo 13. Los ejemplos de como usarlo los podemos encontrar en el código de la aplicación de ejemplo My-simple-web.

Una de las formas de internacionalizar más extendida en los desarrollos web consiste en el uso de la librería ICU, Intl y gettext.

La función gettext en PHP tiene un alias (subrrayado) que hace más compacta la lectura del código, por que permite concentrarse en el texto y no en la función.

Veámos un ejemplo:


   print _('This is a text that have to be translated');    
   print gettext('This line is equivalent to the line above.');    
?>


Para que gettext pueda saber la equivalencia entre el mensaje que queremos mostrar y el que le estamos pasando necesitamos crear un catálogo de traducciones. El programa más extendido para hacer esto se llama PoEdit.


Aunque se puede poner como texto clave la cadena normal tal y como he mostrado en los ejemplos anteriores (esto se hace por si falla la traducción tener un texto en un lenguaje digamos, natural), cada vez más se está extendiendo, sobre todo debido a los frameworks, el uso de etiquetas en las cadenas claves. Esta técnica permite categorizar las entradas del catálogo, y no simplemente tener amontonadas las claves.


Así, un ejemplo habitual siguiendo estas directrices sería:


  
   print _("general.button.label.home");    
?>    


El lector podrá apreciar enseguida que el uso de esa nomenclatura permite tener una estructura arbórea muy conveniente. Así es como funciona por ejemplo www.tradukoj.com, mi proyecto para ayudar a los desarrolladores a centralizar sus cadenas para traducir.

Una vez entendidos estos principios básicos, y teniendo entendido que queremos aprovecharnos de ellos en nuestros desarrollos, vamos a necesitar configurar nuestro intérprete de PHP para que acepte esta orden, ya que no forma parte de la SPL.

Lo habitual es que tengamos que instalar en el sistema la libreria ICU, INTL y el soporte para ambas en PHP.

Vamos a ver los diferentes casos que nos podemos encontrar en función del sistema operativo.

Windows

En este sistema operativo lo habitual es disponer de soporte para PHP mediante alguna de las aplicaciones que vienen como un todo en uno. También conocidas como WAMP (de su homólogo LAMP: Linux-Apache-Mysql-PHP), tenemos con el mismo nombre WAMP; AppServ y XAMPP.

En todas ellas la activación de una librería estándar suele ser un paso muy sencillo. Basta con marcar la librería en la configuración o irse directamente al archivo php.ini y descomentar la línea:
;extension=php_intl.dll


Concretamente, para el caso de Xampp puedes encontrar enlace directo a la edición de php.ini en el programa Panel de control de Xampp


xampp-config

Linux (Ubuntu/Centos y variantes)

Para instalar soporte de idiomas en el S.O Linux, si es que no lo tenemos ya, será suficiente con instalar INTL, ICU y el conector para PHP.



Ubuntu:

sudo apt-get install intl icu php5-intl


Centos:

yum install intl icu php5-intl


OsX

En función de si tenemos MacPorts o Brew instalaremos el soporte de idiomas de esta manera:


Mac Ports:

sudo port install php5-intl


Brew:

brew install php5-intl


En ambos casos para activar la extensión hay que editar php.ini y agregar o descomentar esta línea:

extension=intl.so


En todos los sistemas operativos podemos ver que php.ini usa nuestro sistema lanzando este comando desde la terminal:

php --ini


Ten en cuenta en todo caso que algunos sistemas usan un php.ini para el cli (interfaz de consola) y otro para el servidor web (apache normalmente).

Ahora sólo nos queda comprobar que funciona.

Para que el sistema operativo sepa que idioma estamos esperando cuando le mandamos gettext, necesitamos configurarlo antes que nada, por ello, de manera habitual, en el bootstrap de nuestra aplicación haremos algo como lo que tenemos aquí:


   @bindtextdomain('default', dirname(__FILE__).'/');    
   @textdomain ('default');    
   $langs = array (    
    'es' => 'ES',    
    'en' => 'GB',    
   );    
   $code = isset($_REQUEST['lang'])?$_REQUEST['lang']:'es';    
   if (isset($langs[$code]))    
     $iso_code = $code.'_'.$langs[$code];    
   else{    
     $code = "es";    
     $iso_code = 'es_ES';    
   }    
   if (isset($_SESSION['lang'])) $_SESSION['lang']=$code;    
   putenv ('LANGUAGE='.$iso_code);    
   putenv ("LC_ALL=$iso_code");    
   setlocale(LC_ALL, $iso_code);    
?>



Recuerda: si te da algún error como este:

Fatal error: Call to undefined function _() in ... on line x

Vuelve a repasar la configuración.


En todo caso, si se te resiste el uso de esta librería en local y en producción te funciona correctamente, no es nada descabellado utilizar este truco:


if(!function_exists('_')){
    function _($key){ return $key; }
}

Esto no te traducirá los textos, pero al menos no te romperá el código.

Espero vuestros comentarios.

No hay comentarios:

Publicar un comentario