diff --git a/addons/test_event_full/tests/test_performance.py b/addons/test_event_full/tests/test_performance.py index 76e2e808847..81061e81a9a 100644 --- a/addons/test_event_full/tests/test_performance.py +++ b/addons/test_event_full/tests/test_performance.py @@ -52,7 +52,7 @@ class TestEventPerformance(EventPerformanceCase): batch_size = 20 # simple without type involved + website - with freeze_time(self.reference_now), self.assertQueryCount(event_user=3377): # tef 3275 / com 3274 + with freeze_time(self.reference_now), self.assertQueryCount(event_user=3418): # tef 3316 / com 3315 self.env.cr._now = self.reference_now # force create_date to check schedulers event_values = [ dict(self.event_base_vals, @@ -89,7 +89,7 @@ class TestEventPerformance(EventPerformanceCase): event_type = self.env['event.type'].browse(self.test_event_type.ids) # complex with type + website - with freeze_time(self.reference_now), self.assertQueryCount(event_user=3481): # tef 3379 / com 3378 + with freeze_time(self.reference_now), self.assertQueryCount(event_user=3522): # tef 3420 / com 3419 self.env.cr._now = self.reference_now # force create_date to check schedulers event_values = [ dict(self.event_base_vals, @@ -128,7 +128,7 @@ class TestEventPerformance(EventPerformanceCase): has_social = 'social_menu' in self.env['event.event'] # otherwise view may crash in enterprise # no type, website - with freeze_time(self.reference_now), self.assertQueryCount(event_user=447): # tef 379 / com 427 + with freeze_time(self.reference_now), self.assertQueryCount(event_user=449): # tef 398 / com 399 self.env.cr._now = self.reference_now # force create_date to check schedulers # Require for `website_menu` to be visible #
@@ -150,7 +150,7 @@ class TestEventPerformance(EventPerformanceCase): has_social = 'social_menu' in self.env['event.event'] # otherwise view may crash in enterprise # type and website - with freeze_time(self.reference_now), self.assertQueryCount(event_user=470): # tef 402 / com 450 + with freeze_time(self.reference_now), self.assertQueryCount(event_user=472): # tef 426 / com 428 self.env.cr._now = self.reference_now # force create_date to check schedulers # Require for `website_menu` to be visible #
@@ -212,7 +212,7 @@ class TestEventPerformance(EventPerformanceCase): event_type = self.env['event.type'].browse(self.test_event_type.ids) # complex with type + website - with freeze_time(self.reference_now), self.assertQueryCount(event_user=271): # tef 256 / com 262 + with freeze_time(self.reference_now), self.assertQueryCount(event_user=274): # tef 266 / com 265 self.env.cr._now = self.reference_now # force create_date to check schedulers event_values = dict( self.event_base_vals, diff --git a/addons/website/models/ir_module_module.py b/addons/website/models/ir_module_module.py index b94aa3fff1e..ee83aefcfd2 100644 --- a/addons/website/models/ir_module_module.py +++ b/addons/website/models/ir_module_module.py @@ -189,6 +189,7 @@ class IrModuleModule(models.Model): self.ensure_one() translated_fields = self._theme_translated_fields.get(old_rec._name, []) cur_lang = self.env.lang or 'en_US' + valid_langs = set(code for code, _ in self.env['res.lang'].get_installed()) | {'en_US'} old_rec.flush_recordset() for (src_field, dst_field) in translated_fields: __, src_fname = src_field.split(',') @@ -196,7 +197,11 @@ class IrModuleModule(models.Model): if dst_mname != new_rec._name: continue old_field = old_rec._fields[src_fname] - old_translations = old_field._get_stored_translations(old_rec) + old_translations = { + lang: value + for lang, value in old_field._get_stored_translations(old_rec).items() + if lang in valid_langs + } if not old_translations: continue if not callable(old_field.translate): diff --git a/odoo/addons/base/tests/test_translate.py b/odoo/addons/base/tests/test_translate.py index 23872e94920..449723a4150 100644 --- a/odoo/addons/base/tests/test_translate.py +++ b/odoo/addons/base/tests/test_translate.py @@ -402,6 +402,40 @@ class TestTranslation(TransactionCase): self.assertEqual(categories.ids, [padawans.id, self.customers.id], "Search ordered by translated name should return Padawans (Apprentis) before Customers (Clients)") + def test_105_duplicate_record_multi_no_en(self): + self.env['res.partner'].with_context(active_test=False).search([]).write({'lang': 'fr_FR'}) + self.env['res.lang']._activate_lang('nl_NL') + self.customers.with_context(lang='nl_NL').name = 'Klanten' + self.env['res.lang']._activate_lang('zh_CN') + self.customers.with_context(lang='zh_CN').name = '客户' + self.env.ref('base.lang_en').active = False + self.env.ref('base.lang_zh_CN').active = False + + category = self.customers + translations = category._fields['name']._get_stored_translations(category) + self.assertDictEqual( + translations, + { + 'en_US': 'Customers', + 'fr_FR': 'Clients', + 'nl_NL': 'Klanten', + 'zh_CN': '客户', + } + ) + + category_copy = self.customers.with_context(lang='fr_FR').copy() + translations = category_copy._fields['name']._get_stored_translations(category_copy) + + self.assertDictEqual( + translations, + { + 'en_US': 'Customers', + 'fr_FR': 'Clients', + 'nl_NL': 'Klanten', + }, + 'English, French and Dutch translation should be copied, Chinese translation should be dropped' + ) + def test_107_duplicate_record_en(self): category = self.customers.with_context({'lang': 'en_US'}).copy() diff --git a/odoo/models.py b/odoo/models.py index 009beb6c1bd..f962d7c6668 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -3041,12 +3041,12 @@ class BaseModel(metaclass=MetaModel): """ self.ensure_one() - installed_lang = set(code for code, _ in self.env['res.lang'].get_installed()) - missing_languages = set(translations) - installed_lang - if missing_languages: + valid_langs = set(code for code, _ in self.env['res.lang'].get_installed()) | {'en_US'} + missing_langs = set(translations) - valid_langs + if missing_langs: raise UserError( - _("The following language is not activated: %(missing_names)s", - missing_names=', '.join(missing_languages)) + _("The following languages are not activated: %(missing_names)s", + missing_names=', '.join(missing_langs)) ) field = self._fields[field_name] @@ -4840,6 +4840,7 @@ class BaseModel(metaclass=MetaModel): if old.id in seen_map[old._name]: return seen_map[old._name].add(old.id) + valid_langs = set(code for code, _ in self.env['res.lang'].get_installed()) | {'en_US'} for name, field in old._fields.items(): if not field.copy: @@ -4868,6 +4869,11 @@ class BaseModel(metaclass=MetaModel): continue lang = self.env.lang or 'en_US' old_value_lang = old_translations.pop(lang, old_translations['en_US']) + old_translations = { + lang: value + for lang, value in old_translations.items() + if lang in valid_langs + } if not old_translations: continue if not callable(field.translate):