Update and Extend Translations
This guide explains how to work with the internationalization (i18n) system in Geo Activity Playground. The project uses Flask-Babel for translations, which is based on the standard gettext workflow.
Overview
Translatable strings in templates are wrapped with {{ _('...') }} and in Python code with _('...'). These strings are extracted into .pot (template) and .po (language-specific) files, then compiled into binary .mo files that Flask-Babel uses at runtime.
The translation files are located in:
geo_activity_playground/webui/translations/
├── messages.pot # Template with all extracted strings
└── de/ # German translations
└── LC_MESSAGES/
├── messages.po # Human-editable translation file
└── messages.mo # Compiled binary (generated)
Adding Translatable Strings
When adding new user-facing text, wrap it with the translation function:
In Jinja2 templates:
<h1>{{ _('My Page Title') }}</h1>
<p>{{ _('Welcome to the application!') }}</p>
In Python code:
from flask_babel import gettext as _
flash(_('Activity saved successfully.'), 'success')
Extracting New Strings
After adding new translatable strings, extract them to update the .pot template:
poetry run pybabel extract -F babel.cfg -o geo_activity_playground/webui/translations/messages.pot .
This scans all Python files and Jinja2 templates for _() calls and updates the template file.
Updating Existing Translations
After extracting new strings, update all existing language catalogs:
poetry run pybabel update -i geo_activity_playground/webui/translations/messages.pot -d geo_activity_playground/webui/translations
This merges new strings into each language's .po file, marking them as untranslated (with empty msgstr).
Adding a New Language
To add support for a new language (e.g., French):
-
Initialize the language catalog:
poetry run pybabel init -i geo_activity_playground/webui/translations/messages.pot -d geo_activity_playground/webui/translations -l fr -
Add the language code to the supported locales in
app.py:app.config["BABEL_SUPPORTED_LOCALES"] = ["en", "de", "fr"] -
Edit the generated
.pofile atgeo_activity_playground/webui/translations/fr/LC_MESSAGES/messages.poto add translations.
Editing Translations
The .po files are plain text and can be edited with any text editor. Each entry looks like:
#: geo_activity_playground/webui/templates/page.html.j2:64
msgid "Activities"
msgstr "Aktivitäten"
#:shows where the string is used (file and line number)msgidis the original English stringmsgstris the translation (empty means untranslated)
For a better editing experience, consider using a dedicated PO editor like Poedit or online platforms like Weblate or Transifex.
Compiling Translations
After editing .po files, compile them into binary .mo files:
poetry run pybabel compile -d geo_activity_playground/webui/translations
This must be done before the translations take effect. The .mo files are what Flask-Babel reads at runtime.
Testing Translations
You can test translations by:
- Adding
?lang=de(or another language code) to any URL - Setting your browser's language preference
- The application respects the
Accept-LanguageHTTP header
Quick Reference
| Task | Command |
|---|---|
| Extract strings | poetry run pybabel extract -F babel.cfg -o geo_activity_playground/webui/translations/messages.pot . |
| Update existing languages | poetry run pybabel update -i geo_activity_playground/webui/translations/messages.pot -d geo_activity_playground/webui/translations |
| Add new language | poetry run pybabel init -i geo_activity_playground/webui/translations/messages.pot -d geo_activity_playground/webui/translations -l LANG |
| Compile translations | poetry run pybabel compile -d geo_activity_playground/webui/translations |
Typical Workflow
When working on translations, the typical workflow is:
- Add new
_()wrapped strings in templates or Python code - Extract:
pybabel extract ... - Update:
pybabel update ... - Edit the
.pofiles to add translations - Compile:
pybabel compile ... - Test in the browser