Python gettext i18n — Core Concepts

Internationalization (i18n) means preparing your code so it can be translated. Localization (l10n) means doing the actual translation for a specific language. Python’s gettext module handles both sides.

The Core Workflow

The gettext process has four steps that repeat every time you add or change user-facing text:

  1. Mark translatable strings in your code with _()
  2. Extract those strings into a .pot (Portable Object Template) file
  3. Translate — create .po files for each language
  4. Compile — convert .po files to binary .mo files Python reads at runtime

Step 1: Marking Strings

import gettext

_ = gettext.gettext

print(_("Welcome to the application"))
print(_("You have {} new messages").format(count))

The convention of naming the function _ is universal across gettext-based systems. It keeps code readable without cluttering every string call.

For plural forms, use ngettext:

ngettext = gettext.ngettext
print(ngettext("One file deleted", "{} files deleted", count).format(count))

Step 2: Extracting Strings

The xgettext tool (from GNU gettext) or Python’s pygettext.py scans your source and produces a .pot file:

xgettext -d myapp -o locales/myapp.pot *.py

The .pot file is a catalog of every marked string with blank translation slots.

Step 3: Translation Files

For each language, copy the template into a .po file:

locales/
  fr/LC_MESSAGES/myapp.po
  de/LC_MESSAGES/myapp.po
  ja/LC_MESSAGES/myapp.po

A .po entry looks like:

msgid "Welcome to the application"
msgstr "Bienvenue dans l'application"

Translators edit these files directly or use tools like Poedit, Lokalize, or Weblate.

Step 4: Compiling

msgfmt -o locales/fr/LC_MESSAGES/myapp.mo locales/fr/LC_MESSAGES/myapp.po

The .mo file is a binary lookup table that Python loads efficiently at runtime.

Activating Translations at Runtime

import gettext

lang = gettext.translation("myapp", localedir="locales", languages=["fr"])
lang.install()  # Binds _() to the French catalog globally

print(_("Welcome to the application"))
# Output: Bienvenue dans l'application

For class-based usage without global state:

lang = gettext.translation("myapp", localedir="locales", languages=["de"])
_ = lang.gettext

Fallback Behavior

If a translation file is missing, gettext.translation() raises FileNotFoundError by default. Pass fallback=True to gracefully fall back to the original strings:

lang = gettext.translation("myapp", localedir="locales",
                           languages=["pt"], fallback=True)

Common Misconception

“gettext translates strings automatically.” It doesn’t. gettext is a lookup system — it matches msgid to msgstr in pre-written catalogs. Every translation must be written by a human (or a translation service) and compiled before your app can use it.

Directory Layout Convention

project/
├── locales/
│   ├── myapp.pot
│   ├── fr/LC_MESSAGES/
│   │   ├── myapp.po
│   │   └── myapp.mo
│   └── de/LC_MESSAGES/
│       ├── myapp.po
│       └── myapp.mo
├── app.py

The LC_MESSAGES directory name is required by the gettext standard.

The one thing to remember: gettext is a four-step cycle — mark, extract, translate, compile — and Python’s standard library handles every step except the human translation work.

pythoni18ngettextinternationalizationlocalization

See Also

  • Python Babel Localization Babel teaches your Python app how dates, numbers, and currencies look in every country — not just yours.
  • Python Locale Module Python's locale module reads your computer's regional settings so numbers, dates, and sorting feel right for where you live.
  • Ci Cd Why big apps can ship updates every day without turning your phone into a glitchy mess — CI/CD is the behind-the-scenes quality gate and delivery truck.
  • Containerization Why does software that works on your computer break on everyone else's? Containers fix that — and they're why Netflix can deploy 100 updates a day without the site going down.
  • Python 310 New Features Python 3.10 gave programmers a shape-sorting machine, friendlier error messages, and cleaner ways to say 'this or that' in type hints.