gettext
— Servicios de internacionalización multilingües¶
Código fuente: Lib/gettext.py
El módulo gettext
proporciona servicios de internacionalización (I18N) y localización (L10N) para sus módulos y aplicaciones Python. Admite tanto la API del catálogo de mensajes GNU gettext como una API basada en clases de nivel superior que puede ser más apropiada para los archivos Python. La interfaz que se describe a continuación le permite escribir sus mensajes de módulo y aplicación en un idioma natural, y proporcionar un catálogo de mensajes traducidos para ejecutar en diferentes idiomas naturales.
También se dan algunas sugerencias para localizar sus módulos y aplicaciones Python.
GNU API gettext¶
El módulo gettext
define la siguiente API, que es muy similar al programa GNU gettext API. Si usa esta API, afectará la traducción de toda su aplicación a nivel mundial. A menudo, esto es lo que desea si su aplicación es monolingüe, y la elección del idioma depende de la configuración regional de su usuario. Si está localizando un módulo de Python, o si su aplicación necesita cambiar idiomas sobre la marcha, probablemente desee utilizar la API basada en clases.
- gettext.bindtextdomain(domain, localedir=None)¶
Enlaza (bind) el domain al directorio de configuración regional localedir. Más concretamente,
gettext
buscará archivos binarios.mo
para el dominio dado usando la ruta (en Unix):localedir/language/LC_MESSAGES /domain.mo
, donde se busca language en las variables de entornoLANGUAGE
,LC_ALL
,LC_MESSAGES
yLANG
respectivamente.Si localedir se omite o es
None
, se retorna el enlace actual para domain. [1]
- gettext.textdomain(domain=None)¶
Cambia o consulta el dominio global actual. Si domain es
None
, se retorna el dominio global actual; de lo contrario, el dominio global se establece en domain, que se retorna.
- gettext.gettext(message)¶
Return the localized translation of message, based on the current global domain, language, and locale directory. This function is usually aliased as
_()
in the local namespace (see examples below).
- gettext.dgettext(domain, message)¶
Como
gettext()
, pero busque el mensaje en el domain especificado.
- gettext.ngettext(singular, plural, n)¶
Como
gettext()
, pero considere formas plurales. Si se encuentra una traducción, aplique la fórmula plural a n y retorna el mensaje resultante (algunos idiomas tienen más de dos formas plurales). Si no se encuentra ninguna traducción, retorna singular if n es 1; retorna plural de lo contrario.La fórmula Plural se toma del encabezado del catálogo. Es una expresión C o Python que tiene una variable libre n; la expresión se evalúa como el índice del plural en el catálogo. Consulte la documentación de GNU gettext para conocer la sintaxis precisa que se utilizará en archivos
.po
y las fórmulas para un variedad de idiomas.
- gettext.dngettext(domain, singular, plural, n)¶
Como
ngettext()
, pero busque el mensaje en el domain especificado.
- gettext.pgettext(context, message)¶
- gettext.dpgettext(domain, context, message)¶
- gettext.npgettext(context, singular, plural, n)¶
- gettext.dnpgettext(domain, context, singular, plural, n)¶
Similar a las funciones correspondientes sin la
p
en el prefijo (es decir,gettext()
,dgettext()
,ngettext()
,dngettext()
), pero la traducción está restringida al mensaje dado context.Nuevo en la versión 3.8.
Note that GNU gettext also defines a dcgettext()
method, but
this was deemed not useful and so it is currently unimplemented.
Aquí hay un ejemplo del uso típico de esta API:
import gettext
gettext.bindtextdomain('myapplication', '/path/to/my/language/directory')
gettext.textdomain('myapplication')
_ = gettext.gettext
# ...
print(_('This is a translatable string.'))
API basada en clases¶
The class-based API of the gettext
module gives you more flexibility and
greater convenience than the GNU gettext API. It is the recommended
way of localizing your Python applications and modules. gettext
defines
a GNUTranslations
class which implements the parsing of GNU .mo
format
files, and has methods for returning strings. Instances of this class can also
install themselves in the built-in namespace as the function _()
.
- gettext.find(domain, localedir=None, languages=None, all=False)¶
Esta función implementa el algoritmo de búsqueda de archivos estándar
.mo
. Toma un domain, idéntico al que tomatextdomain()
. Opcional localedir es como enbindtextdomain()
. languages opcionales es una lista de cadenas, donde cada cadena es un código de idioma.Si no se proporciona localedir, se utiliza el directorio de configuración regional predeterminado del sistema. [2] Si no se proporcionan languages, se buscan las siguientes variables de entorno:
LANGUAGE
,LC_ALL
,LC_MESSAGES
, yLANG
. El primero que retorna un valor no vacío se usa para la variable languages. Las variables de entorno deben contener una lista de idiomas separados por dos puntos, que se dividirá en dos puntos para producir la lista esperada de cadenas de código de idioma.find()
luego expande y normaliza los idiomas, y luego los itera, buscando un archivo existente construido con estos componentes:localedir/language/LC_MESSAGES/domain.mo
El primer nombre de archivo que existe es retornado por
find()
. Si no se encuentra dicho archivo, se retornaNone
. Si se proporciona all, retorna una lista de todos los nombres de archivo, en el orden en que aparecen en la lista de idiomas o las variables de entorno.
- gettext.translation(domain, localedir=None, languages=None, class_=None, fallback=False)¶
Return a
*Translations
instance based on the domain, localedir, and languages, which are first passed tofind()
to get a list of the associated.mo
file paths. Instances with identical.mo
file names are cached. The actual class instantiated is class_ if provided, otherwiseGNUTranslations
. The class’s constructor must take a single file object argument.Si se encuentran varios archivos, los archivos posteriores se utilizan como retrocesos para los anteriores. Para permitir la configuración de la reserva,
copy.copy()
se utiliza para clonar cada objeto de traducción del caché; los datos de la instancia real aún se comparten con el caché.Si no se encuentra el archivo
.mo
, esta función generaOSError
si fallback es falso (que es el valor predeterminado) y retorna una instancia deNullTranslations
si fallback is verdadero.Distinto en la versión 3.11: el parámetro codeset se removió.
- gettext.install(domain, localedir=None, *, names=None)¶
This installs the function
_()
in Python’s builtins namespace, based on domain and localedir which are passed to the functiontranslation()
.Para el parámetro names, consulte la descripción del método del objeto de traducción
install()
.As seen below, you usually mark the strings in your application that are candidates for translation, by wrapping them in a call to the
_()
function, like this:print(_('This string will be translated.'))
For convenience, you want the
_()
function to be installed in Python’s builtins namespace, so it is easily accessible in all modules of your application.Distinto en la versión 3.11: names ahora es un parámetro de solo palabra clave.
La clase NullTranslations
¶
Las clases de traducción son las que realmente implementan la traducción de cadenas de mensajes del archivo fuente original a cadenas de mensajes traducidas. La clase base utilizada por todas las clases de traducción es NullTranslations
; Esto proporciona la interfaz básica que puede utilizar para escribir sus propias clases de traducción especializadas. Estos son los métodos de NullTranslations
:
- class gettext.NullTranslations(fp=None)¶
Toma un término opcional file object fp, que es ignorado por la clase base. Inicializa las variables de instancia «protegidas» _info y _charset que se establecen mediante clases derivadas, así como _fallback, que se establece a través de
add_fallback()
. Luego llama aself._parse(fp)
if fp no esNone
.- _parse(fp)¶
No operativo en la clase base, este método toma el objeto de archivo fp y lee los datos del archivo, inicializando su catálogo de mensajes. Si tiene un formato de archivo de catálogo de mensajes no admitido, debe sobrescribir este método para analizar su formato.
- add_fallback(fallback)¶
Agrega fallback como el objeto de respaldo para el objeto de traducción actual. Un objeto de traducción debe consultar la reserva si no puede proporcionar una traducción para un mensaje dado.
- gettext(message)¶
Si se ha establecido una reserva, reenvíe
gettext()
a la reserva. De lo contrario, retorna message. Anulado en clases derivadas.
- ngettext(singular, plural, n)¶
Si se ha establecido una reserva, reenvíe
ngettext()
a la reserva. De lo contrario, retorna singular si n es 1; volver plural de lo contrario. Anulado en clases derivadas.
- pgettext(context, message)¶
Si se ha establecido una reserva, reenvía
pgettext()
a la reserva. De lo contrario, retorna el mensaje traducido. Anulado en clases derivadas.Nuevo en la versión 3.8.
- npgettext(context, singular, plural, n)¶
Si se ha establecido una reserva, reenvía
npgettext()
a la reserva. De lo contrario, retorna el mensaje traducido. Anulado en clases derivadas.Nuevo en la versión 3.8.
- info()¶
Return a dictionary containing the metadata found in the message catalog file.
- charset()¶
Retorna la codificación del archivo de catálogo de mensajes.
- install(names=None)¶
Este método instala
gettext()
en el espacio de nombres incorporado, vinculándolo a_
.If the names parameter is given, it must be a sequence containing the names of functions you want to install in the builtins namespace in addition to
_()
. Supported names are'gettext'
,'ngettext'
,'pgettext'
, and'npgettext'
.Note that this is only one way, albeit the most convenient way, to make the
_()
function available to your application. Because it affects the entire application globally, and specifically the built-in namespace, localized modules should never install_()
. Instead, they should use this code to make_()
available to their module:import gettext t = gettext.translation('mymodule', ...) _ = t.gettext
This puts
_()
only in the module’s global namespace and so only affects calls within this module.Distinto en la versión 3.8: Se agregó
'pgettext'
y'npgettext'
.
La clase GNUTranslations
¶
The gettext
module provides one additional class derived from
NullTranslations
: GNUTranslations
. This class overrides
_parse()
to enable reading GNU gettext format .mo
files
in both big-endian and little-endian format.
GNUTranslations
parses optional metadata out of the translation
catalog. It is convention with GNU gettext to include metadata as
the translation for the empty string. This metadata is in RFC 822-style
key: value
pairs, and should contain the Project-Id-Version
key. If the
key Content-Type
is found, then the charset
property is used to
initialize the «protected» _charset
instance variable, defaulting to
None
if not found. If the charset encoding is specified, then all message
ids and message strings read from the catalog are converted to Unicode using
this encoding, else ASCII is assumed.
Since message ids are read as Unicode strings too, all *gettext()
methods
will assume message ids as Unicode strings, not byte strings.
The entire set of key/value pairs are placed into a dictionary and set as the
«protected» _info
instance variable.
Si el número mágico del archivo .mo
no es válido, el número de versión principal es inesperado, o si se producen otros problemas al leer el archivo, se crea una instancia de GNUTranslations
puede generar OSError
.
- class gettext.GNUTranslations¶
Los siguientes métodos se anulan desde la implementación de la clase base:
- gettext(message)¶
Busca el message id en el catálogo y retorna la cadena de caracteres de mensaje correspondiente, como una cadena Unicode. Si no hay una entrada en el catálogo para el message id, y se ha establecido una retroceso (fallback), la búsqueda se reenvía al método de retroceso
gettext()
. De lo contrario, se retorna el message id.
- ngettext(singular, plural, n)¶
Realiza una búsqueda de formas plurales de una identificación de mensaje. singular se usa como la identificación del mensaje para fines de búsqueda en el catálogo, mientras que n se usa para determinar qué forma plural usar. La cadena del mensaje retornado es una cadena de caracteres Unicode.
Si la identificación del mensaje no se encuentra en el catálogo y se especifica una reserva, la solicitud se reenvía al método de reserva
ngettext()
. De lo contrario, cuando n es 1 se retorna singular, y plural se retorna en todos los demás casos.Aquí hay un ejemplo:
n = len(os.listdir('.')) cat = GNUTranslations(somefile) message = cat.ngettext( 'There is %(num)d file in this directory', 'There are %(num)d files in this directory', n) % {'num': n}
- pgettext(context, message)¶
Busca el context y message id en el catálogo y retorna la cadena de de caracteres mensaje correspondiente, como una cadena de caracteres Unicode. Si no hay ninguna entrada en el catálogo para el message id y context, y se ha establecido un retroceso (fallback), la búsqueda se reenvía al método de retroceso
pgettext()
. De lo contrario, se retorna el message id.Nuevo en la versión 3.8.
- npgettext(context, singular, plural, n)¶
Realiza una búsqueda de formas plurales de una identificación de mensaje. singular se usa como la identificación del mensaje para fines de búsqueda en el catálogo, mientras que n se usa para determinar qué forma plural usar.
Si la identificación del mensaje para context no se encuentra en el catálogo y se especifica una reserva, la solicitud se reenvía al método de reserva
npgettext()
. De lo contrario, cuando n * es 1 se retorna *singular, y plural se retorna en todos los demás casos.Nuevo en la versión 3.8.
Soporte de catálogo de mensajes de Solaris¶
El sistema operativo Solaris define su propio formato de archivo binario .mo
, pero como no se puede encontrar documentación sobre este formato, no es compatible en este momento.
El constructor del catálogo¶
GNOME usa una versión del módulo gettext
de James Henstridge, pero esta versión tiene una API ligeramente diferente. Su uso documentado fue:
import gettext
cat = gettext.Catalog(domain, localedir)
_ = cat.gettext
print(_('hello world'))
For compatibility with this older module, the function Catalog()
is an
alias for the translation()
function described above.
Una diferencia entre este módulo y el de Henstridge: sus objetos de catálogo admitían el acceso a través de una API de mapeo, pero esto parece estar sin usar y, por lo tanto, actualmente no es compatible.
Internacionalizando sus programas y módulos¶
La internacionalización (I18N) se refiere a la operación mediante la cual un programa conoce varios idiomas. La localización (L10N) se refiere a la adaptación de su programa, una vez internacionalizado, al idioma local y los hábitos culturales. Para proporcionar mensajes multilingües para sus programas de Python, debe seguir los siguientes pasos:
prepare su programa o módulo marcando especialmente cadenas traducibles
ejecuta un conjunto de herramientas sobre tus archivos marcados para generar catálogos de mensajes sin procesar
crear traducciones específicas del idioma de los catálogos de mensajes
use el módulo
gettext
para que las cadenas de caracteres de mensajes se traduzcan correctamente
In order to prepare your code for I18N, you need to look at all the strings in
your files. Any string that needs to be translated should be marked by wrapping
it in _('...')
— that is, a call to the function _
. For example:
filename = 'mylog.txt'
message = _('writing a log message')
with open(filename, 'w') as fp:
fp.write(message)
En este ejemplo, la cadena de caracteres 'writing a log message'
está marcada como candidata para la traducción, mientras que las cadenas 'mylog.txt'
y 'w'
no lo están.
Hay algunas herramientas para extraer las cadenas destinadas a la traducción. El GNU gettext original solo admitía el código fuente C o C++, pero su versión extendida xgettext escanea el código escrito en varios idiomas, incluido Python, para encontrar cadenas marcadas como traducibles. Babel es una biblioteca de internacionalización de Python que incluye un script pybabel
para extraer y compilar catálogos de mensajes. El programa de François Pinard llamado xpot hace un trabajo similar y está disponible como parte de su po-utils package.
(Python también incluye versiones de Python puro de estos programas, llamadas pygettext.py y msgfmt.py; algunas distribuciones de Python las instalarán por usted. pygettext.py es similar a xgettext, pero solo entiende el código fuente de Python y no puede manejar otros lenguajes de programación como C o C++. pygettext.py admite una interfaz de línea de comandos similar a xgettext; para detalles sobre su uso, ejecute pygettext.py --help
. msgfmt.py es binario compatible con GNU msgfmt. Con estos dos programas, es posible que no necesite el paquete GNU gettext para internacionalizar sus aplicaciones Python.)
xgettext, pygettext, y herramientas similares generan archivos .po
que son catálogos de mensajes. Son archivos estructurados legibles por humanos que contienen cada cadena marcada en el código fuente, junto con un marcador de posición para las versiones traducidas de estas cadenas.
Las copias de estos archivos .po
se entregan a los traductores humanos individuales que escriben traducciones para cada lenguaje natural compatible. Envían las versiones completas específicas del idioma como un archivo <nombre-idioma >.po
que se compila en un archivo binario .mo
de lectura mecánica utilizando el programa msgfmt . Los archivos .mo
son utilizados por el módulo gettext
para el procesamiento de traducción real en tiempo de ejecución.
Como use el módulo gettext
en su código depende de si está internacionalizando un solo módulo o toda su aplicación. Las siguientes dos secciones discutirán cada caso.
Agregar configuración regional a su módulo¶
Si está aplicando configuración regional a su módulo, debe tener cuidado de no realizar cambios globales, por ejemplo, al espacio de nombres integrado. No debe utilizar la API GNU gettext, sino la API basada en clases.
Digamos que su módulo se llama «spam» y los diversos archivos .mo
de traducciones del lenguaje natural del módulo residen en /usr/share/locale
en formato GNU gettext. Esto es lo que pondría en la parte superior de su módulo:
import gettext
t = gettext.translation('spam', '/usr/share/locale')
_ = t.gettext
Agregar configuración regional a su aplicación¶
If you are localizing your application, you can install the _()
function
globally into the built-in namespace, usually in the main driver file of your
application. This will let all your application-specific files just use
_('...')
without having to explicitly install it in each file.
En el caso simple, entonces, solo necesita agregar el siguiente bit de código al archivo del controlador principal de su aplicación:
import gettext
gettext.install('myapplication')
Si necesita establecer el directorio de configuración regional, puede pasarlo a la función install()
:
import gettext
gettext.install('myapplication', '/usr/share/locale')
Cambiar idiomas sobre la marcha¶
Si su programa necesita admitir muchos idiomas al mismo tiempo, es posible que desee crear varias instancias de traducción y luego cambiar entre ellas explícitamente, de esta manera:
import gettext
lang1 = gettext.translation('myapplication', languages=['en'])
lang2 = gettext.translation('myapplication', languages=['fr'])
lang3 = gettext.translation('myapplication', languages=['de'])
# start by using language1
lang1.install()
# ... time goes by, user selects language 2
lang2.install()
# ... more time goes by, user selects language 3
lang3.install()
Traducciones diferidas¶
En la mayoría de las situaciones de codificación, las cadenas se traducen donde se codifican. Sin embargo, ocasionalmente, debe marcar cadenas para la traducción, pero diferir la traducción real hasta más tarde. Un ejemplo clásico es:
animals = ['mollusk',
'albatross',
'rat',
'penguin',
'python', ]
# ...
for a in animals:
print(a)
Aquí, desea marcar las cadenas en la lista de animals
como traducibles, pero en realidad no desea traducirlas hasta que se impriman.
Aquí hay una manera de manejar esta situación:
def _(message): return message
animals = [_('mollusk'),
_('albatross'),
_('rat'),
_('penguin'),
_('python'), ]
del _
# ...
for a in animals:
print(_(a))
This works because the dummy definition of _()
simply returns the string
unchanged. And this dummy definition will temporarily override any definition
of _()
in the built-in namespace (until the del
command). Take
care, though if you have a previous definition of _()
in the local
namespace.
Note that the second use of _()
will not identify «a» as being
translatable to the gettext program, because the parameter
is not a string literal.
Otra forma de manejar esto es con el siguiente ejemplo:
def N_(message): return message
animals = [N_('mollusk'),
N_('albatross'),
N_('rat'),
N_('penguin'),
N_('python'), ]
# ...
for a in animals:
print(_(a))
In this case, you are marking translatable strings with the function
N_()
, which won’t conflict with any definition of _()
.
However, you will need to teach your message extraction program to
look for translatable strings marked with N_()
. xgettext,
pygettext, pybabel extract
, and xpot all
support this through the use of the -k
command-line switch.
The choice of N_()
here is totally arbitrary; it could have just
as easily been MarkThisStringForTranslation()
.
Agradecimientos¶
Las siguientes personas contribuyeron con código, comentarios, sugerencias de diseño, implementaciones anteriores y una valiosa experiencia para la creación de este módulo:
Peter Funk
James Henstridge
Juan David Ibáñez Palomar
Marc-André Lemburg
Martin von Löwis
François Pinard
Barry Warsaw
Gustavo Niemeyer
Notas al pie