diff --git a/odoo/addons/base/models/ir_translation.py b/odoo/addons/base/models/ir_translation.py index 940708ea0b7..09b344be2a1 100644 --- a/odoo/addons/base/models/ir_translation.py +++ b/odoo/addons/base/models/ir_translation.py @@ -670,6 +670,47 @@ class IrTranslation(models.Model): }) self._modified_model(field.model_name) + @api.model + def _upsert_translations(self, vals_list): + """ Insert or update translations of type 'model' or 'model_terms'. + + This method is used for creations of translations where the given + ``vals_list`` is trusted to be the right values and potential + conflicts should be updated to the new given value. + """ + rows_by_type = defaultdict(list) + for vals in vals_list: + rows_by_type[vals['type']].append(( + vals['name'], vals['lang'], vals['res_id'], vals['src'], vals['type'], + vals.get('module'), vals['value'], vals.get('state'), vals.get('comments'), + )) + + if rows_by_type['model']: + query = """ + INSERT INTO ir_translation (name, lang, res_id, src, type, + module, value, state, comments) + VALUES {} + 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 != ''; + """.format(", ".join(["%s"] * len(rows_by_type['model']))) + self.env.cr.execute(query, rows_by_type['model']) + + if rows_by_type['model_terms']: + query = """ + INSERT INTO ir_translation (name, lang, res_id, src, type, + module, value, state, comments) + VALUES {} + ON CONFLICT (type, name, lang, res_id, md5(src)) + 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 != ''; + """.format(", ".join(["%s"] * len(rows_by_type['model_terms']))) + self.env.cr.execute(query, rows_by_type['model_terms']) + @api.model def translate_fields(self, model, id, field=None): """ Open a view for translating the field(s) of the record (model, id). """ diff --git a/odoo/models.py b/odoo/models.py index 6423e18f314..0972da58928 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -4242,11 +4242,12 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): if vals['lang'] == old.env.lang and field.translate is True: # force a source if the new_val was not changed by copy override if new_val == old[name]: - vals['source'] = old_wo_lang[name] + new_wo_lang[name] = old_wo_lang[name] + vals['src'] = old_wo_lang[name] # the value should be the new value (given by copy()) vals['value'] = new_val vals_list.append(vals) - Translation.create(vals_list) + Translation._upsert_translations(vals_list) @api.multi @api.returns('self', lambda value: value.id)