Skip to content

Localization

quadletman uses Babel and GNU gettext for i18n. The active locale is resolved from the browser's Accept-Language header at the start of each request.

Supported languages: English (en, default) and Finnish (fi).

Key files

File Purpose
quadletman/i18n.py Thin gettext wrapper; set_translations(lang) called by middleware; gettext as _ imported by routers
quadletman/templates_config.py Shared Jinja2Templates instance with i18n Jinja2 extension; _() and ngettext() available in every template
quadletman/locale/quadletman.pot Master message catalog — generated by pybabel extract, committed to the repo
quadletman/locale/{lang}/LC_MESSAGES/quadletman.po Per-language translation catalog (human-edited)
quadletman/locale/{lang}/LC_MESSAGES/quadletman.mo Compiled binary — generated by pybabel compile, committed to the repo
babel.cfg Babel extraction config; maps .py and .html files to extractors

Using translations in code

Python (routers and services):

from quadletman.i18n import gettext as _

raise HTTPException(404, _("Compartment not found"))

Jinja2 templates_() and ngettext() are globals, no import needed:

{{ _("Save") }}
{{ ngettext("%(n)d container", "%(n)d containers", count) % {"n": count} }}

Workflow: adding or changing a translatable string

Every user-visible string must be wrapped in _() (singular) or ngettext() (plural). After adding or changing any such string, run the full catalog update cycle:

# 1. Extract all marked strings into the .pot master catalog
uv run pybabel extract -F babel.cfg -o quadletman/locale/quadletman.pot .

# 2. Merge new/changed strings into each existing .po file
uv run pybabel update -i quadletman/locale/quadletman.pot -d quadletman/locale -D quadletman

# 3. Edit the .po file(s) — translate new or fuzzy entries (see Fuzzy entries below)

# 4. Compile .po → .mo for runtime use
uv run pybabel compile -d quadletman/locale -D quadletman

Commit .pot, all .po files, and the compiled .mo files together in the same commit as the code change.

Fuzzy entries

pybabel update marks auto-guessed translations as #, fuzzy. These are not served at runtime — the fallback string is used instead. Always review and fix fuzzy entries after pybabel update. Remove the #, fuzzy comment once the translation is verified.

Adding a new language

  1. Create the directory: quadletman/locale/{lang}/LC_MESSAGES/
  2. Initialize the catalog:
    uv run pybabel init -i quadletman/locale/quadletman.pot \
      -d quadletman/locale -D quadletman -l {lang}
    
  3. Add the language code to AVAILABLE_LANGS in quadletman/i18n.py.
  4. Translate all msgstr entries in the new .po file.
  5. Compile: uv run pybabel compile -d quadletman/locale -D quadletman

Finnish vocabulary

Use these canonical Finnish terms. Do not invent alternatives.

English Finnish Notes
Container Kontti Plural: kontit; partitive: kontteja; inessive: konteissa. Not "säiliö" or "containerit".
Image Levykuva Plural: levykuvat. Not "säilökuva".
Volume Levyosio
Image store / image registry (local) Levykuvataltio Not "kuvavarasto".
Podman store / Podman storage podman-taltio Lowercase. Not "Podman-varasto".
Podman network podman-verkko Inflects: podman-verkollaan etc. Not "Podman-network".
Non-host containers host-verkkoon kytkeytymättömät kontit Not "ei-host-kontit".
Secret Salaisuus
Compartment Osasto
Cancel Peruuta
Save Tallenna
Delete Poista
Create Luo
Update Päivitä
Add secret Lisää salaisuus
New value Uusi arvo
New secret value… Uusi salaisuuden arvo… Placeholder text.
Secret value… Salaisuuden arvo… Placeholder for new secret.
Name Nimi
Value Arvo
Hook Koukku Notification hooks.
Any container Mikä tahansa kontti

Note: some older strings used "säiliö" for Container. The canonical term is Kontti. Correct any occurrence of "säiliö" found during translation work.

Checklist when adding a user-visible string

  1. Wrap the string in _() or ngettext() at the call site (Python or Jinja2).
  2. Run the full extract → update → translate → compile cycle.
  3. For Finnish: verify the term against the vocabulary table above.
  4. Stage .pot, .po, and .mo files in the same commit.