diff --git a/addons/web/static/src/core/l10n/dates.js b/addons/web/static/src/core/l10n/dates.js index c7441b673a5..e2cfa3c6cc5 100644 --- a/addons/web/static/src/core/l10n/dates.js +++ b/addons/web/static/src/core/l10n/dates.js @@ -3,7 +3,7 @@ import { memoize } from "../utils/functions"; import { sprintf } from "../utils/strings"; import { localization } from "./localization"; -import { _lt } from "./translation"; +import { _t } from "./translation"; const { DateTime } = luxon; @@ -276,7 +276,7 @@ export function parseDateTime(value, options = {}) { } if (!result) { - throw new Error(sprintf(_lt("'%s' is not a correct date or datetime").toString(), value)); + throw new Error(sprintf(_t("'%s' is not a correct date or datetime"), value)); } result = result.toUTC(); diff --git a/addons/web/static/src/core/l10n/localization_service.js b/addons/web/static/src/core/l10n/localization_service.js index 57193e37ccb..5163869341b 100644 --- a/addons/web/static/src/core/l10n/localization_service.js +++ b/addons/web/static/src/core/l10n/localization_service.js @@ -4,7 +4,7 @@ import { browser } from "../browser/browser"; import { registry } from "../registry"; import { strftimeToLuxonFormat } from "./dates"; import { localization } from "./localization"; -import { translatedTerms } from "./translation"; +import { translatedTerms, _t } from "./translation"; export const localizationService = { dependencies: ["user"], @@ -33,9 +33,6 @@ export const localizationService = { } Object.setPrototypeOf(translatedTerms, terms); - function _t(str) { - return terms[str] || str; - } env._t = _t; env.qweb.translateFn = _t; const dateFormat = strftimeToLuxonFormat(userLocalization.date_format); diff --git a/addons/web/static/src/core/l10n/translation.js b/addons/web/static/src/core/l10n/translation.js index 354e2cf0ea0..dec843ea2ea 100644 --- a/addons/web/static/src/core/l10n/translation.js +++ b/addons/web/static/src/core/l10n/translation.js @@ -2,6 +2,31 @@ export const translatedTerms = {}; +/** + * Translate a term, or return the term if no translation can be found. + * + * Note that it translates eagerly, which means that if the translations have + * not been loaded yet, it will return the untranslated term. If it cannot be + * guaranteed that translations are ready, one should use the _lt function + * instead (see below) + * + * @param {string} term + * @returns {string} + */ +export function _t(term) { + return translatedTerms[term] || term; +} + +class LazyTranslatedString extends String { + valueOf() { + const str = super.valueOf(); + return _t(str); + } + toString() { + return this.valueOf(); + } +} + /** * Lazy translation function, only performs the translation when actually * printed (e.g. inserted into a template). @@ -12,7 +37,7 @@ export const translatedTerms = {}; * @returns {{toString: () => string}} */ export function _lt(str) { - return { toString: () => translatedTerms[str] || str }; + return new LazyTranslatedString(str); } /* diff --git a/addons/web/static/tests/core/l10n/translation_tests.js b/addons/web/static/tests/core/l10n/translation_tests.js index c87136c01e1..ded6e1df950 100644 --- a/addons/web/static/tests/core/l10n/translation_tests.js +++ b/addons/web/static/tests/core/l10n/translation_tests.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { translatedTerms } from "@web/core/l10n/translation"; +import { translatedTerms, _lt } from "@web/core/l10n/translation"; import { registry } from "@web/core/registry"; import { patch, unpatch } from "@web/core/utils/patch"; import { makeTestEnv } from "../../helpers/mock_env"; @@ -27,6 +27,23 @@ QUnit.test("can translate a text node", async (assert) => { unpatch(translatedTerms, "add translations"); }); +QUnit.test("can lazy translate", async (assert) => { + assert.expect(3); + + TestComponent.template = owl.tags.xml`
`; + TestComponent.someLazyText = _lt("Hello"); + assert.strictEqual(TestComponent.someLazyText.toString(), "Hello"); + assert.strictEqual(TestComponent.someLazyText.valueOf(), "Hello"); + + serviceRegistry.add("localization", makeFakeLocalizationService()); + const env = await makeTestEnv(); + patch(translatedTerms, "add translations", terms); + const target = getFixture(); + await mount(TestComponent, { env, target }); + assert.strictEqual(target.innerText, "Bonjour"); + unpatch(translatedTerms, "add translations"); +}); + QUnit.test("_t is in env", async (assert) => { assert.expect(1); TestComponent.template = owl.tags.xml`
`;