Extracción¶
La extracción es el paso que recopila todos los mensajes marcados en tu código
fuente en una plantilla .pot para los traductores: el paso 3 del ciclo del
tutorial. Esta página es la referencia de ese paso: la
configuración, los nombres de función propios, el modo estricto para CI y las
comprobaciones que después protegen tus catálogos.
La extracción necesita el extra babel:
El flujo de trabajo¶
Crea babel.cfg:
Después utiliza los comandos habituales de Babel:
pybabel extract -F babel.cfg -c "Translators:" -o locales/messages.pot .
pybabel init -i locales/messages.pot -d locales -l ja
pybabel compile -d locales
init se ejecuta una sola vez por idioma; a partir de ahí, pybabel update
incorpora cada plantilla nueva a los catálogos existentes. Ese ciclo
recurrente —y qué significan sus entradas fuzzy para una versión— se recorre
en En producción.
El extractor gettext_tstrings también procesa llamadas ordinarias a _(),
gettext() y ngettext(), de modo que un solo mapping cubre una base de código
mixta. Reconoce _(), los cuatro nombres estándar de gettext, los alias tr() /
ntr() y las funciones diferidas lazy_gettext() / lazy_pgettext().
Activa los comentarios para traductores con -c
pybabel extract solo recoge los comentarios para traductores si se pasa
-c "Translators:", exactamente igual que con las llamadas gettext
ordinarias. Si lo omites, la extracción sigue funcionando: lo que pasa es
que los comentarios nunca llegan al catálogo, donde son la palanca de
calidad más barata de
todo el flujo de trabajo.
Registrar nombres de función propios¶
Un archivo ini proporciona una cadena y un mapping TOML proporciona una lista; dentro de una cadena, tanto los espacios como las comas separan los nombres. Las cuatro variantes funcionan.
Las opciones son tr_functions, ntr_functions, gettext_functions,
ngettext_functions, pgettext_functions y npgettext_functions.
-k no llega a una t-string
Un helper propio como mytr(t"…") debe registrarse en una de las opciones
anteriores. El mecanismo --keyword de Babel no puede leer un literal
t-string, por lo que pybabel extract -k mytr no encuentra nada ni muestra
ningún aviso: los mensajes simplemente no aparecen en el POT. -k sigue
funcionando para las llamadas gettext ordinarias extraídas al mismo tiempo.
Solo se admite el orden de argumentos estándar: primero el mensaje; en
pgettext, contexto y mensaje; en npgettext, contexto, singular y plural.
Permisivo en local, estricto en CI¶
Por defecto, un archivo incorrecto no detiene la ejecución:
- Una t-string rechazada por el extractor —acceso a atributos, una expresión o un argumento incorrecto— se notifica como advertencia y se omite.
- Un archivo que no puede analizarse se omite de la misma forma.
- También se omite un archivo que solo rechaza
tokenizeaunqueastlo acepte, ya que de otro modo el propio paso de Babel se detendría.
Eso resulta cómodo mientras estás editando y peligroso cuando no lo estás: un
mensaje omitido está sencillamente ausente del POT, así que nunca se traduce
y nada lo advierte. Establece strict = true en las opciones del mapping allí
donde ninguna persona esté vigilando la extracción:
Con ello, todas las advertencias anteriores pasan a ser errores. Considera esta la configuración de producción y la anterior la de trabajo local.
El toolchain existente valida estos catálogos¶
Babel marca cada mensaje extraído con un flag estándar. Esa línea activa la validación de marcadores en las herramientas que ya utilizas:
Si se traduce como こんにちは {nombre}, el error se detecta sin configuración:
$ msgfmt --check-format -o /dev/null locales/ja/LC_MESSAGES/messages.po
locales/ja/LC_MESSAGES/messages.po:25: a format specification for argument
'name' doesn't exist in 'msgstr'
msgfmt: found 1 fatal error
Weblate documenta la misma comprobación como Python brace format, y las plataformas comerciales tienen su propio QA de marcadores basado en el mismo flag. El comportamiento de cada plataforma es cosa suya; las dos herramientas siguientes son las verificadas aquí.
Además, el paquete registra un checker de Babel, por lo que
pybabel compile aplica las reglas de la especificación a cada mensaje con el
comentario marcador gettext-tstrings:
$ pybabel compile -d locales -l ja
error: locales/ja/LC_MESSAGES/messages.po:24: translation does not match the
source placeholders: {name} is missing; {nombre} is not in the source message
1 errors encountered.
En un mensaje plural el indicador nombra la forma, porque el número de línea que
informa Babel es el del msgid y un bloque ruso tiene tres msgstr debajo:
error: locales/ru/LC_MESSAGES/messages.po:31: msgstr[1]: translation does not
match the source placeholders: {n} is missing
pybabel compile escribe el .mo de todos modos
El error anterior se informa, el estado de salida es 1, y aun así el
catálogo incorrecto se compila. Solo ese estado de salida puede impedir que
un pipeline lo publique; Qué controla la CI
muestra el paso de compilación que lo permite.
Las dos comprobaciones no son redundantes. El checker del paquete es más estricto al menos en dos casos:
- Un msgid cuyas únicas llaves están escapadas (
Config {{raw}} only) nunca recibe el flagpython-brace-format, así que ninguna herramienta externa lo valida. - Las formas plurales se comprueban una a una.
msgfmt --check-formatlee el archivo anterior y devuelve0; acepta una forma que omite un marcador presente en sus formas hermanas, mientras que este checker la rechaza.
msgfmt solo comprueba nombres que puede interpretar como formato de llaves de
Python. Los nombres ASCII permiten que todas las herramientas de la cadena
validen el mensaje. La propia biblioteca acepta cualquier nombre para el que
str.isidentifier() sea verdadero.
Templates y otras herramientas¶
Las t-strings son sintaxis de Python, por lo que esta biblioteca cubre código
Python. Los lenguajes de template siguen usando su propia i18n —{% trans %} de
Jinja2, las etiquetas de Django— y sus extractores de Babel. Todo alimenta el
mismo catálogo PO, de modo que una sola traducción sigue cubriendo una base de
código mixta.
pygettext no puede analizar t-strings actualmente, por eso la extracción se
realiza mediante Babel. La convención se documenta en la
especificación para que otro extractor, o un futuro pygettext,
pueda implementarla.