Skip to content

translation-not-lazy (ODOO059)

Preview (since 0.16.2.9) · Related issues · View source

Derived from the odoo linter.

Fix is sometimes available.

This rule is unstable and in preview. The --preview flag is required for use.

What it does

Checks for translation calls that interpolate values eagerly with the % operator or string concatenation (_("Hello %s") % name, _("Hello %s" % name), _("Hello " + name)) instead of passing them as arguments to the translation function.

Why is this bad?

Since Odoo 14.0 the translation functions (_, self.env._) interpolate the values themselves: _("Hello %s", name). Interpolating before the call translates the already-interpolated text, so the term never matches the exported translation entry. Interpolating after the call works, but bypasses Odoo's own interpolation and, for lazy translations, forces the evaluation at definition time instead of rendering time.

Example

_("Hello %s") % name

Use instead:

_("Hello %s", name)

Fix safety

A fix is offered when the interpolated values can be moved into the translation call faithfully: a tuple becomes positional arguments (_("%s %s") % (a, b) becomes _("%s %s", a, b)), a dict literal with valid identifier keys becomes keyword arguments (_("%(name)s") % {"name": name} becomes _("%(name)s", name=name)), and any other single value becomes one positional argument when the term only uses positional placeholders.

The fix is marked unsafe because it relies on the translation-function signature introduced in Odoo 14.0, and because a function named _ that is not Odoo's translation function (e.g. gettext.gettext) does not accept the extra arguments.