Jugando con archivos de idioma .po y .mo

La eterna duda de planteamiento en cuanto a localización de un proyecto -l10n ó multi-idioma para despistados-. Se puede resolver en forma de constantes en un archivo que se cargue al inicio dependiendo del idioma:
es.php:
define('USER','Usuario');
define('PASS', 'Contraseña');

en.php:
define('USER','User');
define('PASS', 'Password');

if($_SESSION['lang']=='es') include('es.php');
También se puede abordar el problema desde el mismo punto de vista pero cambiando constantes por variables, lo cual no sé hasta qué punto podría ser lógico puesto que realmente se trata de cadenas que no variarán a lo largo de la ejecución del script. Y por último -atm- se pueden usar los archivos de idiomas soportados por la biblioteca de funciones gettext();, más conocidos por archivos .po y .mo. Ignoro si el consumo de recursos es mayor ó menor que las soluciones anteriores, pero como hay que probar de todo, análogamente al ejemplo anterior creamos un fichero.po con el siguiente contenido:
msgid "User"
msgstr "Usuario"

msgid "Pass"
msgstr "Contraseña"
Ahora debemos compilarlo para convertirlo en .mo y cargarlo en nuestra aplicación:
$ msgfmt -o fichero.mo fichero.po
Haremos lo mismo con el resto de idiomas pero ubicándolos en distintas carpetas siguiendo una estructura similar a la siguiente:
  • /lang
    • en_US
      • LC_MESSAGES
        • fichero.po
        • fichero.mo
    • es_ES
      • LC_MESSAGES
        • fichero.po
        • fichero.mo
Tan solo queda la lógica del script, en la que le diremos el idioma a cargar y dónde se encuentra:
// Cargamos locale e idioma
setlocale(LC_ALL, 'es_ES'); 
bindtextdomain('fichero', '/lang/');
textdomain('fichero');
Recordad que el uso -si se cambia de idioma- es similar al anterior:
if($_SESSION['lang']=='en') setlocale(LC_ALL, 'en_US');
Creo que no me dejo nada en el tintero... bueno, la función que pinta todo ésto podría ser algo similar a ésto -seguro que os suena-:
/**
 * Gettext pero más cómodo
 */
function __($var)
{
	return gettext($var);
}
Con un simple <?=__('User');?> arreglaríamos, como veis es bastante "vistoso" -esto va con segundas-. Ahora si, post acabado.

Ojo: Las locales (es_ES, en_US...) varían según el sistema operativo.
code

About the author

Óscar
has doubledaddy super powers, father of Hugo and Nico, husband of Marta, *nix user, Djangonaut and open source passionate.