From abe2ec83ad4a2df60aefc27d0ef8fe5205b318dc Mon Sep 17 00:00:00 2001 From: xO-Tx Date: Wed, 21 Dec 2022 10:00:09 +0000 Subject: [PATCH] [FIX] website: fix homepage translation overwriting To reproduce the issue: - Go to website > Add language > Add blocks to your homepage and translate it. - Make translations on the "Contact us" page (or a new custom page). - Install a new app > The translation of the homepage is lost (only on homepage). Explanation: After [1], The `_load_module_terms()` method was updated on website module to copy translations from base to specific views when module translation is loaded. And since [2], the translated field's column is either NULL or a JSON dict mapping language codes to text (the field's value in the corresponding language). To explain what happens exactly when new app is installed, let's suppose we want to load module translation for the config {'en_US', 'fr_BE'} in the following situations: S1 (e.g. "Contact us" page): -=-=-=-=-=-=--=-=-=-=-=-=-=- ``` generic_arch_db = { 'en_US': '
Generic (EN)
', 'fr_BE': '
Generic (FR)
' } - specific_arch_db = { 'en_US': '
Specific (EN)
', 'fr_BE': '
Specific (FR)
' } ``` `_load_module_terms()` will copy translations for 'fr_BE' from generic to specific `arch_db` (using generic translation dictionary). result: ``` new_specific_arch_db = { 'en_US': '
Specific (EN)
', 'fr_BE': '
Updated Specific (FR)
' } ``` S2 (new custom page): -=-=-=-=-=-=--=-=-=-= ``` generic_arch_db = NULL specific_arch_db = { 'en_US': '
Specific (EN)
', 'fr_BE': '
Specific (FR)
' } ``` result: Nothing to do here (only specific version), the specific translation will not be updated. S3 (e.g. website homepage): -=-=-=-=-=-=--=-=-=-=-=-=-= The generic view has no translated `arch_db` (only the 'en_US' version): ``` generic_arch_db = {'en_US': '
Generic (EN)
'} specific_arch_db = { 'en_US': '
Specific (EN)
', 'fr_BE': '
Specific (FR)
' } ``` `_load_module_terms()` will copy generic translations only for languages available on "generic_arch_db" and the 'fr_BE' version will be lost. result: `new_specific_arch_db = {'en_US': '
Specific (EN)
'}` The goal of this commit is to prevent this behaviour by keeping the specific translated `arch_db` even when the generic value has no content for the translation language. Remark: This behaviour occurred while loading module translations, as a consequence, the specific translations are also lost when the website module is updated. [1]: https://github.com/odoo/odoo/commit/94db81d8d28c4cbc7b51ae1688c9362042ee3619 [2]: https://github.com/odoo/odoo/commit/ef00294e7189359c47638c4a71626f1937395edb opw-3083480 closes odoo/odoo#108477 X-original-commit: 91a9c870eede96040ac49d2375fe0e18342342e1 Signed-off-by: Romain Derie (rde) --- addons/website/models/ir_module_module.py | 3 ++- addons/website/tests/test_views.py | 11 ++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/addons/website/models/ir_module_module.py b/addons/website/models/ir_module_module.py index c5051a2a545..019519ce71a 100644 --- a/addons/website/models/ir_module_module.py +++ b/addons/website/models/ir_module_module.py @@ -501,10 +501,11 @@ class IrModuleModule(models.Model): if not generic_arch_db: continue langs_update = (langs & generic_arch_db.keys()) - {'en_US'} + specific_langs = (langs & specific_arch_db.keys()) - {'en_US'} generic_arch_db_en = generic_arch_db.pop('en_US') specific_arch_db_en = specific_arch_db.pop('en_US') generic_arch_db = {k: generic_arch_db[k] for k in langs_update} - specific_arch_db = {k: specific_arch_db.get(k, specific_arch_db_en) for k in langs_update} + specific_arch_db = {k: specific_arch_db.get(k, specific_arch_db_en) for k in specific_langs} generic_translation_dictionary = field.get_translation_dictionary(generic_arch_db_en, generic_arch_db) specific_translation_dictionary = field.get_translation_dictionary(specific_arch_db_en, specific_arch_db) # update specific_translation_dictionary diff --git a/addons/website/tests/test_views.py b/addons/website/tests/test_views.py index a039f42b219..30689189db5 100644 --- a/addons/website/tests/test_views.py +++ b/addons/website/tests/test_views.py @@ -1010,12 +1010,21 @@ class TestCowViewSaving(TestViewSavingCommon): self.assertEqual(specific_view.with_context(lang='fr_BE').arch, '
bonjour
', "updating translation of base view doesn't update specific view") - self.env['ir.module.module']._load_module_terms(['website'], ['en_US', 'fr_BE'], overwrite=True) + self.env['res.lang']._activate_lang('es_ES') + # Translate specific 'arch_db' while the generic value has no content for the + # translation language. + specific_view.update_field_translations('arch_db', {'es_ES': {'hello': 'hola'}}) + self.assertEqual(specific_view.with_context(lang='es_ES').arch, '
hola
') + + self.env['ir.module.module']._load_module_terms(['website'], ['en_US', 'fr_BE', 'es_ES'], overwrite=True) specific_view.invalidate_model(['arch_db', 'arch']) self.assertEqual(specific_view.with_context(lang='fr_BE').arch, '
salut
', "loading module translation copy translation from base to specific view") + self.assertEqual(specific_view.with_context(lang='es_ES').arch, '
hola
', + "loading module translation should not remove specific translations that are not available on base view") + def test_soc_complete_flow(self): """ Check the creation of views from specific-website environments.