[FIX] base: single lang behaviour
If a db is in single lang (en_US or not) but still has translations, the translation should be updated in addition to updating the referenced record Add tests to formalise the expected behaviour: If one language only (en_US or not), when writing on a translatable field: - record field should updated - value of potential existing en_US translation should be updated - src of potential existing translations should be updated - no new translation should be created If en_US and fr_FR, when writing on a translatable field in en_US: - record field should updated - value of potential existing en_US translation should be updated - src of potential existing translations should be updated - new en_US translation should be created if was not present If en_US and fr_FR, when writing on a translatable field in fr_FR: - record field should not be updated - value of potential existing fr_FR translation should be updated - src of potential existing translations should not be updated - new fr_FR translation should be created if was not present Adapt test_new_api test get_installed is ormcached, just putting active = True is not enough
This commit is contained in:
@@ -649,6 +649,30 @@ class IrTranslation(models.Model):
|
||||
""".format(", ".join(["%s"] * len(rows_by_type['model_terms'])))
|
||||
self.env.cr.execute(query, rows_by_type['model_terms'])
|
||||
|
||||
def _update_translations(self, vals_list):
|
||||
""" Update translations of type 'model' or 'model_terms'.
|
||||
|
||||
This method is used for update of translations where the given
|
||||
``vals_list`` is trusted to be the right values
|
||||
No new translation will be created
|
||||
"""
|
||||
grouped_rows = {}
|
||||
for vals in vals_list:
|
||||
key = (vals['lang'], vals['type'], vals['name'])
|
||||
grouped_rows.setdefault(key, [vals['value'], vals['src'], vals['state'], []])
|
||||
grouped_rows[key][3].append(vals['res_id'])
|
||||
|
||||
for where, values in grouped_rows.items():
|
||||
self._cr.execute(
|
||||
""" UPDATE ir_translation
|
||||
SET value=%s,
|
||||
src=%s,
|
||||
state=%s
|
||||
WHERE lang=%s AND type=%s AND name=%s AND res_id in %s
|
||||
""",
|
||||
(values[0], values[1], values[2], where[0], where[1], where[2], tuple(values[3]))
|
||||
)
|
||||
|
||||
@api.model
|
||||
def translate_fields(self, model, id, field=None):
|
||||
""" Open a view for translating the field(s) of the record (model, id). """
|
||||
|
||||
@@ -393,6 +393,92 @@ class TestTranslation(TransactionCase):
|
||||
])
|
||||
self.assertEqual(translation_fr.src, 'Customers', "Did not set English version as source")
|
||||
|
||||
class TestTranslationWrite(TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.category = self.env['res.partner.category'].create({'name': 'Reblochon'})
|
||||
|
||||
def test_01_en(self):
|
||||
langs = self.env['res.lang'].get_installed()
|
||||
self.assertEqual([('en_US', 'English (US)')], langs, "Test did not started with expected languages")
|
||||
|
||||
self.category.with_context(lang='en_US').write({'name': 'English Name'})
|
||||
name = self.category.with_context(lang=None).read(['name'])
|
||||
self.assertEqual(name[0]['name'], "English Name", "Reference field not updated")
|
||||
translations = self.env['ir.translation'].search([
|
||||
('name', '=', 'res.partner.category,name'),
|
||||
('res_id', '=', self.category.id),
|
||||
('lang', '=', 'en_US'),
|
||||
])
|
||||
self.assertEqual(len(translations), 0, "No English translation should be created when writing in English")
|
||||
|
||||
def test_02_en_translated(self):
|
||||
langs = self.env['res.lang'].get_installed()
|
||||
self.assertEqual([('en_US', 'English (US)')], langs, "Test did not started with expected languages")
|
||||
translation = self.env['ir.translation'].create({
|
||||
'type': 'model',
|
||||
'name': 'res.partner.category,name',
|
||||
'lang': 'en_US',
|
||||
'res_id': self.category.id,
|
||||
'src': 'Reblochon',
|
||||
'value': 'Translated Name',
|
||||
'state': 'translated',
|
||||
})
|
||||
|
||||
self.category.with_context(lang='en_US').write({'name': 'English Name'})
|
||||
translation_value = translation.read(['value'])
|
||||
self.assertEqual(translation_value[0]['value'], "English Name", "Existing translation was not updated")
|
||||
|
||||
source_name = self.category.with_context(lang=None).read(['name'])
|
||||
self.assertEqual(source_name[0]['name'], "English Name", "Reference field not updated")
|
||||
|
||||
def test_03_fr_single(self):
|
||||
self.env['res.lang'].load_lang('fr_FR')
|
||||
self.env['res.users'].with_context(active_test=False).search([]).write({'lang': 'fr_FR'})
|
||||
self.env.ref('base.lang_en').active = False
|
||||
|
||||
langs = self.env['res.lang'].get_installed()
|
||||
self.assertEqual([('fr_FR', 'French / Français')], langs, "Test did not started with expected languages")
|
||||
|
||||
self.category.with_context(lang='fr_FR').write({'name': 'French Name'})
|
||||
source_name = self.category.with_context(lang=None).read(['name'])
|
||||
self.assertEqual(source_name[0]['name'], "French Name", "Reference field not updated")
|
||||
translations = self.env['ir.translation'].search([
|
||||
('name', '=', 'res.partner.category,name'),
|
||||
('res_id', '=', self.category.id),
|
||||
('lang', '=', 'fr_FR'),
|
||||
])
|
||||
self.assertEqual(len(translations), 0, "No French translation should be created when writing in French")
|
||||
|
||||
def test_04_fr_multi(self):
|
||||
self.env['res.lang'].load_lang('fr_FR')
|
||||
|
||||
langs = self.env['res.lang'].get_installed()
|
||||
self.assertEqual([('en_US', 'English (US)'), ('fr_FR', 'French / Français')], langs,
|
||||
"Test did not started with expected languages")
|
||||
self.env['ir.translation'].create({
|
||||
'type': 'model',
|
||||
'name': 'res.partner.category,name',
|
||||
'lang': 'en_US',
|
||||
'res_id': self.category.id,
|
||||
'src': 'Reblochon',
|
||||
'value': 'Translated Name',
|
||||
'state': 'translated',
|
||||
})
|
||||
|
||||
self.category.with_context(lang='fr_FR').write({'name': 'French Name'})
|
||||
self.category.with_context(lang='en_US').write({'name': 'English Name'})
|
||||
translations = self.env['ir.translation'].search([
|
||||
('name', '=', 'res.partner.category,name'),
|
||||
('res_id', '=', self.category.id),
|
||||
], order='lang')
|
||||
self.assertRecordValues(translations, [
|
||||
{'src': 'English Name', 'value': 'English Name', 'lang': 'en_US'},
|
||||
{'src': 'English Name', 'value': 'French Name', 'lang': 'fr_FR'}
|
||||
])
|
||||
|
||||
|
||||
|
||||
class TestXMLTranslation(TransactionCase):
|
||||
def setUp(self):
|
||||
|
||||
@@ -1230,8 +1230,7 @@ class TestFields(common.TransactionCase):
|
||||
email = self.env.ref('test_new_api.emailmessage_0_0')
|
||||
self.assertEqual(email.message, message)
|
||||
|
||||
french = self.env['res.lang']._lang_get('fr_FR')
|
||||
french.active = True
|
||||
self.env['res.lang'].load_lang('fr_FR')
|
||||
|
||||
def count(msg):
|
||||
# return the number of translations of msg.label
|
||||
|
||||
+10
-3
@@ -3397,6 +3397,12 @@ Fields:
|
||||
other_fields = [] # list of non-column fields
|
||||
single_lang = len(self.env['res.lang'].get_installed()) <= 1
|
||||
has_translation = self.env.lang and self.env.lang != 'en_US'
|
||||
# when there is only one language, update existing translations but
|
||||
# do not create new ones
|
||||
if single_lang:
|
||||
process_translations = self.env['ir.translation']._update_translations
|
||||
else:
|
||||
process_translations = self.env['ir.translation']._upsert_translations
|
||||
|
||||
for name, val in vals.items():
|
||||
field = self._fields[name]
|
||||
@@ -3411,7 +3417,7 @@ Fields:
|
||||
val = field.convert_to_column(val, self, vals)
|
||||
columns.append((name, field.column_format, val))
|
||||
tname = "%s,%s" % (self._name, name)
|
||||
if field.translate is True and not single_lang:
|
||||
if field.translate is True and self.env.lang:
|
||||
self.env['ir.translation']._set_source(tname, self.ids, val)
|
||||
updated.append(name)
|
||||
else:
|
||||
@@ -3451,7 +3457,7 @@ Fields:
|
||||
# synchronize translated terms when possible.
|
||||
self.env['ir.translation']._sync_terms_translations(field, self)
|
||||
|
||||
elif has_translation and field.translate:
|
||||
elif self.env.lang and field.translate:
|
||||
# The translated value of a field has been modified.
|
||||
src_trans = self.with_context(lang=None).read([name])[0][name]
|
||||
if not src_trans:
|
||||
@@ -3469,7 +3475,8 @@ Fields:
|
||||
state='translated',
|
||||
res_id=res_id) for res_id in self.ids]
|
||||
|
||||
self.env['ir.translation']._upsert_translations(translation_values)
|
||||
if translation_values:
|
||||
process_translations(translation_values)
|
||||
|
||||
# mark fields to recompute; do this before setting other fields, because
|
||||
# the latter can require the value of computed fields, e.g., a one2many
|
||||
|
||||
Reference in New Issue
Block a user