Manage translations¶
DicoGIS is shipped in English (source language), French and Spanish. Two separate mechanisms coexist, split by whether the graphical interface is involved:
What you are translating |
Mechanism |
Files |
|---|---|---|
Widget text: buttons, labels, tabs, tooltips, message boxes |
Qt native translations |
|
Report and CLI output: Excel sheet names, column headers, error messages |
|
|
The rule of thumb: anything under dicogis/ui/ uses self.tr("..."), anything reachable from dicogis-cli uses TextsManager. The command-line interface must keep working without the gui extra installed, which is precisely why the processing pipeline does not depend on Qt’s translation machinery.
GUI widget text (Qt translations)¶
Required tools¶
pylupdate6, which extracts the translatable strings, ships with PyQt6 itself: installing the gui extra is enough.
python -m pip install -U -e .[gui]
lrelease, which compiles the translations, and Qt Linguist, the graphical editor, come from the Qt 6 tools. On Ubuntu:
sudo apt install qt6-l10n-tools linguist-qt6
Note
Ubuntu installs those binaries in /usr/lib/qt6/bin/, which is not on the PATH by default. Either call them with their full path or add the folder to your PATH:
export PATH="/usr/lib/qt6/bin:$PATH"
Workflow¶
Write the widget text through
self.tr(), so it can be extracted:self.btn_cancel.setText(self.tr("Cancel"))
Update the
.tsfiles, once per language.pylupdate6reads the wholedicogispackage (Python modules and Qt Designer forms) and merges: existing translations are preserved, new strings are added as untranslated entries.for lang in fr es; do pylupdate6 dicogis --ts dicogis/ui/i18n/dicogis_$lang.ts done
Translate the new entries, either with Qt Linguist:
linguist dicogis/ui/i18n/dicogis_fr.ts dicogis/ui/i18n/dicogis_es.ts
or directly in the
.tsfiles, replacing every<translation type="unfinished" />with the translated text:<message> <location filename="../mw_dicogis.py" line="247" /> <source>Cancel</source> <translation>Annuler</translation> </message>
Compile the
.qmfiles loaded at runtime. They are not versioned, so compile them locally to see your translations in the application:for lang in fr es; do lrelease dicogis/ui/i18n/dicogis_$lang.ts -qm dicogis/ui/i18n/dicogis_$lang.qm done
lreleasecomes fromqt6-l10n-tools(Ubuntu) or frompyside6-essentials(python -m pip install pyside6-essentials, where the command ispyside6-lrelease). Without compiled files, the interface stays in English.Check your work:
DICOGIS_I18N_STRICT=1 pytest tests/test_ui_i18n.py
That suite fails, naming the offending strings, when a
self.tr()string has no translation in a shipped locale.The completeness check (every
self.tr()string translated) is skipped unless theDICOGIS_I18N_STRICTenvironment variable is true, because translations are legitimately incomplete while a feature is under development. The CI enables it only on tags and onrelease/*branches (including pull requests opened from one), so a release cannot ship an untranslated interface.
English is the source language¶
There is no English .ts file: the strings of self.tr() calls are already English, so with no translator installed Qt returns them as they are. DicoGIS._install_qt_translator() accordingly removes any installed translator and returns early for EN.
Report and CLI text (TextsManager)¶
Strings written to the output file or printed by the command line live in dicogis/locale/lang_{EN,FR,ES}.xml, one XML element per key:
<nomfic>Filename</nomfic>
TextsManager.load_texts() reads the file matching the requested language into a localized_strings dictionary, which is passed explicitly down the pipeline — to ProcessingFiles and to the serializers. Adding a string means adding the same key to the three files: a key missing from one of them silently serializes as an empty cell, since lookups go through dict.get().
Add a new language¶
Add it to
AvailableLocalesindicogis/constants.py. That enum feeds the GUI language dropdown and the CLI’s--languageoption.Create
dicogis/locale/lang_XX.xml, copyinglang_EN.xmland translating every value.Create and compile
dicogis/ui/i18n/dicogis_xx.ts/.qm, following the workflow above. Mind the case: the enum values are uppercase (FR), the translation filenames lowercase (dicogis_fr.qm).Add the matching OS locale to
DicoGIS._apply_locale()indicogis/ui/mw_dicogis.py, which setslocale.setlocale()per platform.
Notes¶
The compiled
.qmfiles are not tracked. The CI test jobs and the release builds compile them from the.tsfiles before tests and packaging, so a shipped.qmcannot be outdated. They are declared as package data inpyproject.toml..tsfiles record the source line of every string, so re-runningpylupdate6after unrelated edits produces<location>churn in the diff. That is expected.Qt matches translations on the exact source string, context included, so rewording an existing
self.tr()string orphans its translation: it comes back as a new untranslated entry, and the old one is markedvanished.