From 543a5523a30c993f60eba3c6d56d54dea2857eb3 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Tue, 17 Sep 2019 15:17:04 +0000 Subject: [PATCH] [FIMP] base: remove all translations when writing False This "bugprovement" resolve the old issue of writing on a translatable field a falsy value. Before this commit, only the translation value was removed. When no translation is present (or when the value is not set), the value is retrieved directly from the source field. Before 18d9c2cab2426, it was still possible to go around this issue by removing manually all ir.translation entries and writing with a user in en_US. This is no longer possible as writing on a translatable field always uses translations when in multi-language environment, without exception of en_US. When writing a falsy value on a field, the expected behaviour is to reset the value and see that falsy value after saving, not the old value stored on the source model. Remove all translations and force to update the column. Removing one individual translation is still possible in the translation popup. Task id: 2062415 closes odoo/odoo#37077 Signed-off-by: Martin Trigaux (mat) --- odoo/addons/base/tests/test_translate.py | 52 ++++++++++++++++++++++++ odoo/fields.py | 14 +++++-- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/odoo/addons/base/tests/test_translate.py b/odoo/addons/base/tests/test_translate.py index ab0a852910a..715d1b778a5 100644 --- a/odoo/addons/base/tests/test_translate.py +++ b/odoo/addons/base/tests/test_translate.py @@ -481,6 +481,58 @@ class TestTranslationWrite(TransactionCase): ]) + def test_05_remove_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") + + belgium = self.env.ref('base.be') + # vat_label is translatable and not required + belgium.with_context(lang='en_US').write({'vat_label': 'VAT'}) + + # create translations if not exists + self.env['ir.translation']._upsert_translations([{ + 'type': 'model', + 'name': 'res.country,vat_label', + 'lang': 'en_US', + 'res_id': belgium.id, + 'src': 'VAT', + 'value': 'VAT', + 'state': 'translated', + }, { + 'type': 'model', + 'name': 'res.country,vat_label', + 'lang': 'fr_FR', + 'res_id': belgium.id, + 'src': 'VAT', + 'value': 'TVA', + 'state': 'translated', + }]) + + # remove the value + belgium.with_context(lang='fr_FR').write({'vat_label': False}) + # should recover the initial value from db + self.assertEqual( + False, belgium.with_context(lang='fr_FR').vat_label, + "Value was not reset" + ) + self.assertEqual( + False, belgium.with_context(lang='en_US').vat_label, + "Value was not reset in other languages" + ) + self.assertEqual( + False, belgium.with_context(lang=None).vat_label, + "Value was not reset on the field model" + ) + + translations = self.env['ir.translation'].search([ + ('name', '=', 'res.country,vat_label'), + ('res_id', '=', belgium.id), + ]) + self.assertEqual(len(translations), 0, "Translations were not removed") + def test_field_selection(self): """ Test translations of field selections. """ field = self.env['ir.model']._fields['state'] diff --git a/odoo/fields.py b/odoo/fields.py index dc685d7885b..2576fd770ac 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -1435,8 +1435,8 @@ class _String(Field): update_column = True update_trans = True elif lang != 'en_US': - # update the translations only - update_column = False + # update the translations only except if emptying + update_column = cache_value is None update_trans = True # update towrite if modifying the source @@ -1445,7 +1445,7 @@ class _String(Field): for rid in real_recs._ids: # cache_value is already in database format towrite[rid][self.name] = cache_value - if self.translate is True: + if self.translate is True and cache_value is not None: tname = "%s,%s" % (records._name, self.name) records.env['ir.translation']._set_source(tname, real_recs._ids, value) @@ -1464,7 +1464,13 @@ class _String(Field): source_recs[self.name] = value source_value = value tname = "%s,%s" % (self.model_name, self.name) - if single_lang: + if value is None: + records.env['ir.translation'].search([ + ('name', '=', tname), + ('type', '=', 'model'), + ('res_id', 'in', real_recs._ids) + ]).unlink() + elif single_lang: records.env['ir.translation']._update_translations([dict( src=source_value, value=value,