diff --git a/addons/website/models/__init__.py b/addons/website/models/__init__.py index 378acd4f300..b66ecb50a24 100644 --- a/addons/website/models/__init__.py +++ b/addons/website/models/__init__.py @@ -14,6 +14,7 @@ from . import website_menu from . import website_page from . import website_rewrite from . import ir_rule +from . import ir_translation from . import ir_ui_view from . import res_company from . import res_partner diff --git a/addons/website/models/ir_translation.py b/addons/website/models/ir_translation.py new file mode 100644 index 00000000000..16528b7b27e --- /dev/null +++ b/addons/website/models/ir_translation.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models + +class IrTranslation(models.Model): + _inherit = "ir.translation" + + def _load_module_terms(self, modules, langs, overwrite=False): + """ Add missing website specific translation """ + res = super()._load_module_terms(modules, langs) + + default_menu = self.env.ref('website.main_menu', raise_if_not_found=False) + + if not default_menu or not langs or not modules: + return res + + if overwrite: + conflict_clause = """ + ON CONFLICT (type, lang, name, res_id) WHERE type = 'model' + DO UPDATE SET (name, lang, res_id, src, type, value, module, state, comments) = + (EXCLUDED.name, EXCLUDED.lang, EXCLUDED.res_id, EXCLUDED.src, EXCLUDED.type, + EXCLUDED.value, EXCLUDED.module, EXCLUDED.state, EXCLUDED.comments) + WHERE EXCLUDED.value IS NOT NULL AND EXCLUDED.value != '' + """; + else: + conflict_clause = " ON CONFLICT DO NOTHING" + + # Add specific menu translations + self.env.cr.execute(""" + INSERT INTO ir_translation(name, lang, res_id, src, type, value, module, state, comments) + SELECT DISTINCT ON (s_menu.id, t.lang) t.name, t.lang, s_menu.id, t.src, t.type, t.value, t.module, t.state, t.comments + FROM ir_translation t + INNER JOIN website_menu o_menu + ON t.type = 'model' AND t.name = 'website.menu,name' AND t.res_id = o_menu.id + INNER JOIN website_menu s_menu + ON o_menu.name = s_menu.name AND o_menu.url = s_menu.url + INNER JOIN website_menu root_menu + ON s_menu.parent_id = root_menu.id AND root_menu.parent_id IS NULL + WHERE t.lang IN %s and t.module IN %s + AND o_menu.website_id IS NULL AND o_menu.parent_id = %s + AND s_menu.website_id IS NOT NULL""" + conflict_clause, + (tuple(langs), tuple(modules), default_menu.id)) + + return res diff --git a/addons/website/tests/test_menu.py b/addons/website/tests/test_menu.py index a410e3ed0eb..672eea114d4 100644 --- a/addons/website/tests/test_menu.py +++ b/addons/website/tests/test_menu.py @@ -65,6 +65,47 @@ class TestMenu(common.TransactionCase): Website.create({'name': 'new website'}) self.assertEqual(total_menus + 4, Menu.search_count([]), "New website's bootstraping should have duplicate default menu tree (Top/Home/Contactus/Sub Default Menu)") + def test_specific_menu_translation(self): + Translation = self.env['ir.translation'] + Website = self.env['website'] + Menu = self.env['website.menu'] + existing_menus = Menu.search([]) + + default_menu = self.env.ref('website.main_menu') + template_menu = Menu.create({ + 'parent_id': default_menu.id, + 'name': 'Menu in english', + 'url': 'turlututu', + }) + new_menus = Menu.search([]) - existing_menus + specific1, specific2 = new_menus.with_context(lang='fr_FR') - template_menu + + # create fr_FR translation for template menu + self.env.ref('base.lang_fr').active = True + template_menu.with_context(lang='fr_FR').name = 'Menu en français' + Translation.search([ + ('name', '=', 'website.menu,name'), ('res_id', '=', template_menu.id), + ]).module = 'website' + self.assertEqual(specific1.name, 'Menu in english', + 'Translating template menu does not translate specific menu') + + # have different translation for specific website + specific1.name = 'Menu in french' + + # loading translation add missing specific translation + Translation._load_module_terms(['website'], ['fr_FR']) + Menu.invalidate_cache(['name']) + self.assertEqual(specific1.name, 'Menu in french', + 'Load translation without overwriting keep existing translation') + self.assertEqual(specific2.name, 'Menu en français', + 'Load translation add missing translation from template menu') + + # loading translation with overwrite sync all translations from menu template + Translation._load_module_terms(['website'], ['fr_FR'], overwrite=True) + Menu.invalidate_cache(['name']) + self.assertEqual(specific1.name, 'Menu en français', + 'Load translation with overwriting update existing menu from template') + def test_default_menu_unlink(self): Menu = self.env['website.menu'] total_menu_items = Menu.search_count([])