Cómo hacer programas multilingües con Python
Copyright © 27 de Mayo de 2003 por Lorenzo Gil Sánchez (lgs)
Con esta receta explicaré como hacer un programa muy simple que soporte varios idiomas. Lo haremos cubriendo todos los pasos, algo que ningún documento, al menos que yo haya podido encontrar, trata completamente.
Mi entorno actual es el siguiente: RedHat 9.0 y Python 2.2 y espero que puedas usar esta receta para cualquier otro sistema que tenga Python a partir de la versión 2. La librería que usaremos para la localización (l10n) es gettext, que por supuesto es software libre.
El primer paso es escribir el código de nuestro programa y marcar los textos que queremos poder traducir posteriormente. Por ejemplo:
1 import gettext
2 t = gettext.translation('holamundo', '/home/lgs/recetas/idiomas')
3 _ = t.ugettext
4
5 print _('hello world')
Supongamos que este script se llama hola.py y esta ubicado en el directorio/home/lgs/recetas. La linea 5 es la que hace el trabajo útil y la que tiene la cadena de texto traducible dentro de nuestro programa. Esto se sabe porque esta dentro de la función _(), que es un alias a la función t.ugettext como se puede ver en la linea 3. Esto es algo muy común en los programas que usan gettext para evitar tener que escribir la función ugettext cada vez.
En la linea 2 estamos diciendole a gettext que nuestra aplicación se llama holamundo y que los directorios con el soporte para los distintos idiomas están en /home/lgs/recetas/idiomas.
Una vez que tenemos el código, es necesario utilizar la utilidad pygettext para extraer todas las cadenas traducibles del código a un fichero independiente. Esta herramienta no está en mi path por lo que primero he de buscarla:
lgs@i8100:$find /usr/lib/python2.2/ -name "pygettext.py"
/usr/lib/python2.2/site-packages/Ft/Lib/pygettext.py
Ahora que ya sé donde está ejecuto este comando:
lgs@i8100:$python /usr/lib/python2.2/site-packages/Ft/Lib/pygettext.py -k_ -ohola.po hola.py
Y así obtengo el fichero hola.po que contiene lo siguiente:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"PO-Revision-Date: Wed May 28 00:56:08 2003\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.1\n"
#: hola.py:5
msgid "hello world"
msgstr ""
Como veis, este fichero no es mas que una lista de pares (msgid, msgstr) donde el primer par es la metainformación. Este es el fichero que los traductores de nuestro software han de traducir. Por ejemplo, vamos a traducir nuestra aplicación al español por lo que cogemos ese archivo y lo editamos para obtener lo siguiente:
# Ejemplo de programa multilingüe
# Copyright (C) 2003 lgs
# Lorenzo Gil Sánchez <loren@fedro.ugr.es>, 2003.
#
msgid ""
msgstr ""
"Project-Id-Version: 0.1\n"
"PO-Revision-Date: Wed May 28 00:56:08 2003\n"
"Last-Translator: Lorenzo Gil Sánchez <loren@fedro.ugr.es>\n"
"Language-Team: es <es@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-15\n"
"Content-Transfer-Encoding: iso-8859-15\n"
"Generated-By: pygettext.py 1.1\n"
#: hola.py:5
msgid "hello world"
msgstr "hola mundo"
El siguiente paso es crear un archivo binario .mo a partir del fichero .po. Este fichero binario será el que usará gettext durante la ejecución de nuestro programa:
lgs@i8100:$python /usr/lib/python2.2/site-packages/Ft/Lib/msgfmt hola.po -o hola.mo
Ahora ya sólo nos falta situar ese archivo en el sitio adecuado. En nuestro programa hola.py habiamos puesto en la linea 2 que nuestro directorio de traducciones sería /home/lgs/recetas/idiomas. Ahora tenemos que crear los siguientes directorios ahi: /home/lgs/recetas/idiomas/es/LC_MESSAGES/ y ahi es donde tenemos que poner el archivo hola.mo, generado en el paso anterior:
lgs@i8100:$mkdir /home/lgs/recetas/idiomas/es
lgs@i8100:$mkdir /home/lgs/recetas/idiomas/es/LC_MESSAGES
lgs@i8100:$cp hola.mo /home/lgs/recetas/idiomas/es/LC_MESSAGES/
La explicación es la siguiente: cuando ejecutamos un programa que use gettext la función gettext.translation intentará localizar el fichero .mo de la aplicación siguiendo el siguiente algoritmo:
1. Mira las variables de entorno LANGUAGE, LC_ALL, LC_MESSAGES y LANG. La primera de estas variables que devuelva un valor no nulo se usará para el campo idioma
2. El campo directorio es igual al valor del segundo argumento que le pasamos a la función gettext.translation.
3. El archivo que gettext utiliza para las traducciones es el siguiente: directorio/idioma/LC_MESSAGES/programa.mo , donde programa es el primer argumento que le pasamos a la función gettext.translation
Por tanto, para probar nuestro ejemplo debemos asegurarnos de que una de esas variables de entorno esta puesta a "es" por ser el código ISO 639 de nuestro idioma:
lgs@i8100:$export LANG="es"
Ahora ejecutamos nuestro programa y...:
lgs@i8100:$python hola.py
hola mundo
Para más información consulta estos enlaces:
- "Manual de gettext":"http://www.gnu.org/manual/gettext/index.html"
- "Módulo gettext de Python":"http://www.python.org/doc/current/lib/module-gettext.html"
- "Página sobre gettext de Christian Reis":"http://www.async.com.br/~kiko/gettext.html"





