Translations not showing up?#
Odoo’s translation loader (odoo/tools/translate.py) silently skips more
than you would expect. This page explains why a translation does not appear,
which odoo-lint rule detects it, and how to reload translations. It is based
on the Odoo 18.0 and 19.0 sources.
How Odoo reads a .po file#
For a language such as nl_BE, Odoo reads i18n/nl.po, i18n/nl_BE.po and
the same names in i18n_extra/, in that order: the more specific file wins.
Merge with the template. When the module has an
i18n/<module>.pot, Odoo first merges the.pofile with it, likemsgmerge. Entries whosemsgidis not in the template become obsolete and are skipped, and the#.comments and#:references are taken from the template.Module comment. Every entry needs
#. module: <module>; without it reading the file fails.References.
#: model:...and#: model_terms:...entries translate records and views;#: code:...entries translate_()in Python and JavaScript. Other references are ignored with an error in the log.Empty and fuzzy. Empty translations are skipped. Fuzzy ones are not: Odoo loads them as if they were reviewed.
Symptom |
Cause |
Rule |
|---|---|---|
New translation never shows |
|
|
|
reference Odoo cannot read, often in the |
|
Code translations of a module all missing in one language |
|
|
A whole language file is ignored |
file not named after a language code |
|
Unreviewed text shown to users |
|
|
Translation file fails to load |
syntax error |
|
One of two translations lost on the next export |
duplicate |
Fixing translation files#
odl check --fix repairs what can be repaired mechanically: it adds missing
#. module: comments, adds :0 to code: references, merges identical
duplicates and sorts the file the way OCA’s po-pretty-format does. Review
with --diff first.
--unsafe-fixes also copies translations whose msgid is missing from the
.pot into the template, untranslated and with only the references Odoo can
read. Entries that only have references Odoo cannot read, or that label a
field the template already labels differently, are left alone: they are
translations of old texts. Regenerate the .pot from a running Odoo when
possible; the fix is for when that is not practical.
Reloading translations#
Even a correct file only shows up once Odoo reloads it, and that differs per kind of translation:
_()in Python and JavaScript (#: code:)Read from the
.pofiles on first use and cached per worker process. Restart the server; updating the module does not reload them.- Records and views (
#: model:and#: model_terms:) Stored in the database when the module is installed or updated. An update does not overwrite translations that already exist: use
odoo-bin -u <module> --i18n-overwrite, or Settings > Translations > Import with Overwrite Existing Terms. Records loaded withnoupdate="1"are only overwritten by a forced import.
The language itself must be installed and active, or nothing is loaded for it.