python-gettext

The preset for gettext in Python, as in Django, Flask-Babel and Babel. It reads .po catalogs, gettext calls and Django translate tags.

The python-gettext preset supports gettext in Python projects: Django, Flask-Babel and Babel.

Detection

The preset applies when pyproject.toml or requirements.txt has django or flask-babel. babel alone does not count: it is also the name of an old npm package, and x18n merges the dependencies of all manifests. A project that uses only Babel or the gettext module of the standard library must list the preset:

import { defineConfig } from '@x18n/core'

export default defineConfig({
  presets: ['python-gettext'],
})

Locale files

If your config has no resources, the preset uses these patterns:

  • locale/{locale}/LC_MESSAGES/*.po and */locale/{locale}/LC_MESSAGES/*.po, as Django writes them for the project and for each app
  • translations/{locale}/LC_MESSAGES/*.po and */translations/{locale}/LC_MESSAGES/*.po, as Flask-Babel reads them

The po format reads and writes these catalogs. Each msgid is a key, and its msgstr is the value:

locale/de/LC_MESSAGES/django.po
msgid "Welcome, %(name)s!"
msgstr "Willkommen, %(name)s!"

Supported syntax

In .py files, the preset reads calls of _, gettext, gettext_lazy, gettext_noop, lazy_gettext, _l, _lazy, ngettext, ngettext_lazy and lazy_ngettext, and the u forms of Python 2. The key is the first string argument, the source message:

shop/views.py
from django.utils.translation import gettext as _, ngettext

msg = _("Welcome, %(name)s!") % {"name": name}
n = ngettext("One apple", "%(count)d apples", count)

These usages are Welcome, %(name)s! and One apple.

In .html, .jinja, .jinja2 and .j2 templates, the preset reads the same calls, as in Jinja {{ _("Log out") }}, and the Django tags {% translate "Log out" %} and {% trans "Log out" %}, also with noop or as name.

The preset does not read:

  • f-strings, string concatenation and keys with escapes such as \"
  • pgettext, npgettext and {% translate "x" context "y" %}: in the catalog, their key holds the context too
  • {% blocktranslate %} blocks

Keys for extracted strings

The preset sets extract.keygen to source, so x18n extract uses the text itself as the key. Set extract.keygen in the config to change it.

Placeholders

Python percent formatting: %(name)s, %s, %d. %%, a % before a space and URL escapes such as %2F, or %20 in a URL, are text.

Extraction templates

KindsTemplate
any_("{key}")