[FIX] core: fix copy translations
after odoo #113888 when copy translations from one record to another, translations for non-installed languages may raise error. These translations may be 1. created before the langauge is deactivated 2. en_US which is always available for non falsy translated field value this commit drops translations for uninstalled languages except 'en_US' when copy and prevents raising error when users want to translate en_US when en_US is not activated closes odoo/odoo#115711 X-original-commit: 7bb1825ddbf2340882bef5ed1d9c877f78a2b815 Signed-off-by: Raphael Collet <rco@odoo.com> Signed-off-by: Wang Chong (cwg) <cwg@odoo.com>
This commit is contained in:
@@ -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
|
||||
# <div name="event_menu_configuration" groups="base.group_no_one">
|
||||
@@ -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
|
||||
# <div name="event_menu_configuration" groups="base.group_no_one">
|
||||
@@ -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,
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
+11
-5
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user