From 1bb9cb89c8b5b5c55299afd3c53df14c3aea5ee7 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Mon, 8 Nov 2021 15:07:13 +0000 Subject: [PATCH] [FIX] web: setup luxon locale from user lang Before this commit, luxon wasn't configured with respect to the user lang, meaning that months weren't translated (for instance, in the filter menu, date(time) filter options, or in the datepicker displayed in the "Add custom filter" sub-drodown). closes odoo/odoo#79644 X-original-commit: 9530b0a2462aca0938ce315cee262b147b7a5634 Signed-off-by: Julien Mougenot (jum) Signed-off-by: Aaron Bohy (aab) --- .../static/src/core/datepicker/datepicker.js | 6 +-- .../src/core/l10n/localization_service.js | 10 ++++ .../web/static/tests/core/datepicker_tests.js | 35 +++++++++++++- .../tests/core/l10n/translation_tests.js | 46 +++++++++++++++++-- 4 files changed, 90 insertions(+), 7 deletions(-) diff --git a/addons/web/static/src/core/datepicker/datepicker.js b/addons/web/static/src/core/datepicker/datepicker.js index 82d96f5c615..bc221c5f535 100644 --- a/addons/web/static/src/core/datepicker/datepicker.js +++ b/addons/web/static/src/core/datepicker/datepicker.js @@ -146,13 +146,13 @@ export class DatePicker extends Component { if (typeof commandOrParams === "object") { const format = luxonFormatToMomentFormat(this.props.format || this.defaultFormat); const params = { ...commandOrParams, format }; + if (!params.locale && commandOrParams.date) { + params.locale = commandOrParams.date.locale; + } for (const prop in params) { if (params[prop] instanceof DateTime) { const luxonDate = params[prop]; const momentDate = luxonDateToMomentDate(luxonDate); - if (momentDate.locale() !== luxonDate.locale) { - momentDate.locale(params.locale); - } params[prop] = momentDate; } } diff --git a/addons/web/static/src/core/l10n/localization_service.js b/addons/web/static/src/core/l10n/localization_service.js index c24d20abbe9..a240dcf4793 100644 --- a/addons/web/static/src/core/l10n/localization_service.js +++ b/addons/web/static/src/core/l10n/localization_service.js @@ -41,6 +41,16 @@ export const localizationService = { Object.setPrototypeOf(translatedTerms, terms); env._t = _t; env.qweb.translateFn = _t; + + // Setup lang inside luxon. The locale codes received from the server contain "_", whereas + // the Intl codes use "-" (Unicode BCP 47). There's only one exception, which is locale + // "sr@latin", for which we manually fallback to the "sr-Latn-RS" locale. + if (lang === "sr@latin") { + luxon.Settings.defaultLocale = "sr-Latn-RS"; + } else if (lang) { + luxon.Settings.defaultLocale = lang.replace(/_/g, "-"); + } + const dateFormat = strftimeToLuxonFormat(userLocalization.date_format); const timeFormat = strftimeToLuxonFormat(userLocalization.time_format); const dateTimeFormat = `${dateFormat} ${timeFormat}`; diff --git a/addons/web/static/tests/core/datepicker_tests.js b/addons/web/static/tests/core/datepicker_tests.js index f0da030c8b7..6b9f7359832 100644 --- a/addons/web/static/tests/core/datepicker_tests.js +++ b/addons/web/static/tests/core/datepicker_tests.js @@ -127,7 +127,7 @@ QUnit.module("Components", () => { assert.verifySteps(["datetime-changed"]); }); - QUnit.test("pick a date with locale", async function (assert) { + QUnit.test("pick a date with locale (locale given in props)", async function (assert) { assert.expect(5); const picker = await mountPicker(DatePicker, { @@ -158,6 +158,39 @@ QUnit.module("Components", () => { assert.verifySteps(["datetime-changed"]); }); + QUnit.test("pick a date with locale (locale from date props)", async function (assert) { + assert.expect(5); + + const picker = await mountPicker(DatePicker, { + props: { + date: DateTime.fromFormat("09/01/1997", "dd/MM/yyyy", { + zone: "utc", + locale: useFRLocale(), + }), + format: "dd MMM, yyyy", + }, + onDateChange: (ev) => { + assert.step("datetime-changed"); + assert.strictEqual( + ev.detail.date.toFormat("dd/MM/yyyy"), + "01/09/1997", + "Event should transmit the correct date" + ); + }, + }); + const input = picker.el.querySelector(".o_datepicker_input"); + + assert.strictEqual(input.value, "09 janv., 1997"); + + await click(input); + await click(document.querySelector(".datepicker .picker-switch")); // month picker + await click(document.querySelectorAll(".datepicker .month")[8]); // september + await click(document.querySelector(".datepicker .day")); // first day + + assert.strictEqual(input.value, "01 sept., 1997"); + assert.verifySteps(["datetime-changed"]); + }); + QUnit.test("enter a date value", async function (assert) { assert.expect(5); diff --git a/addons/web/static/tests/core/l10n/translation_tests.js b/addons/web/static/tests/core/l10n/translation_tests.js index ded6e1df950..3bfe6d1848e 100644 --- a/addons/web/static/tests/core/l10n/translation_tests.js +++ b/addons/web/static/tests/core/l10n/translation_tests.js @@ -1,11 +1,15 @@ /** @odoo-module **/ +import { browser } from "@web/core/browser/browser"; import { translatedTerms, _lt } from "@web/core/l10n/translation"; +import { localizationService } from "@web/core/l10n/localization_service"; import { registry } from "@web/core/registry"; import { patch, unpatch } from "@web/core/utils/patch"; -import { makeTestEnv } from "../../helpers/mock_env"; -import { makeFakeLocalizationService } from "../../helpers/mock_services"; -import { getFixture } from "../../helpers/utils"; +import { session } from "@web/session"; +import { makeTestEnv } from "@web/../tests/helpers/mock_env"; +import { makeFakeLocalizationService } from "@web/../tests/helpers/mock_services"; +import { getFixture, patchWithCleanup } from "@web/../tests/helpers/utils"; +import { registerCleanup } from "@web/../tests/helpers/cleanup"; const { mount } = owl; @@ -55,3 +59,39 @@ QUnit.test("_t is in env", async (assert) => { assert.strictEqual(target.innerText, "Bonjour"); unpatch(translatedTerms, "add translations"); }); + +QUnit.test("luxon is configured in the correct lang", async (assert) => { + const defaultLocale = luxon.Settings.defaultLocale; + registerCleanup(() => { + luxon.Settings.defaultLocale = defaultLocale; + }); + patchWithCleanup(session, { + user_context: {...session.user_context, lang: "fr_BE"}, + }); + patchWithCleanup(browser, { + fetch() { + return { + ok: true, + json() { + return { + modules: {}, + lang_parameters: { + direction: "ltr", + date_format: "%d/%m/%Y", + time_format: "%H:%M:%S", + grouping: "[3,0]", + decimal_point: ",", + thousands_sep: ".", + week_start: 1, + }, + }; + }, + }; + }, + }); + serviceRegistry.add("localization", localizationService); + + await makeTestEnv(); + + assert.strictEqual(luxon.DateTime.utc(2021, 12, 10).toFormat("MMMM"), "décembre"); +});