From c3756b7d9aa71fd929be3b6ed71d492de37e272e Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Tue, 22 Nov 2016 11:33:10 +0100 Subject: [PATCH] [FIX] base: avoid duplicated translations after update This commits fixes the following scenario: 1. load the translations for any language 2. modify the source of a translated record (e.g. email template body) 3. click on 'load translations' button (flag) 4. execute the translation wizard for the same language (to refresh) The translation of the modified record was duplicated. This was due to the field src in the database being different than the msgid in the po file. The src value is updated on the insert_missing call. The matching on src for type='model' translations is only needed due to the translations that are split (e.g. xml views or html content). For the other translations, matching on the rec_id is enough. Detects the xml_translate and html_translate fields to avoid matching on src for these translations. opw-691752 Closes #14310 --- openerp/addons/base/ir/ir_translation.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/openerp/addons/base/ir/ir_translation.py b/openerp/addons/base/ir/ir_translation.py index 6d51c614bc2..16922523bb0 100644 --- a/openerp/addons/base/ir/ir_translation.py +++ b/openerp/addons/base/ir/ir_translation.py @@ -5,7 +5,7 @@ from collections import defaultdict from difflib import get_close_matches import logging -from openerp import api, tools +from openerp import api, tools, SUPERUSER_ID import openerp.modules from openerp.osv import fields, osv from openerp.tools.translate import _ @@ -126,12 +126,21 @@ class ir_translation_import_cursor(object): # referencing non-existent data. cr.execute("DELETE FROM %s WHERE res_id IS NULL AND module IS NOT NULL" % self._table_name) + # detect the xml_translate fields, where the src must be the same + env = api.Environment(cr, SUPERUSER_ID, {}) + src_relevant_fields = [] + for model in env: + for field_name, field in env[model]._fields.items(): + if hasattr(field, 'translate') and callable(field.translate): + src_relevant_fields.append("%s,%s" % (model, field_name)) + find_expr = """ irt.lang = ti.lang AND irt.type = ti.type AND irt.name = ti.name AND ( - (ti.type = 'model' AND ti.res_id = irt.res_id AND irt.src = ti.src) + (ti.type = 'model' AND ti.res_id = irt.res_id AND ti.name IN %s AND irt.src = ti.src) + OR (ti.type = 'model' AND ti.res_id = irt.res_id AND ti.name NOT IN %s) OR (ti.type = 'view' AND (irt.res_id IS NULL OR ti.res_id = irt.res_id) AND irt.src = ti.src) OR (ti.type = 'field') OR (ti.type = 'help') @@ -147,20 +156,23 @@ class ir_translation_import_cursor(object): state = 'translated' FROM %s AS ti WHERE %s AND ti.value IS NOT NULL AND ti.value != '' - """ % (self._parent_table, self._table_name, find_expr)) + """ % (self._parent_table, self._table_name, find_expr), + (tuple(src_relevant_fields), tuple(src_relevant_fields))) # Step 3: insert new translations cr.execute("""INSERT INTO %s(name, lang, res_id, src, type, value, module, state, comments) SELECT name, lang, res_id, src, type, value, module, state, comments FROM %s AS ti WHERE NOT EXISTS(SELECT 1 FROM ONLY %s AS irt WHERE %s); - """ % (self._parent_table, self._table_name, self._parent_table, find_expr)) + """ % (self._parent_table, self._table_name, self._parent_table, find_expr), + (tuple(src_relevant_fields), tuple(src_relevant_fields))) if self._debug: cr.execute('SELECT COUNT(*) FROM ONLY %s' % self._parent_table) c1 = cr.fetchone()[0] cr.execute('SELECT COUNT(*) FROM ONLY %s AS irt, %s AS ti WHERE %s' % \ - (self._parent_table, self._table_name, find_expr)) + (self._parent_table, self._table_name, find_expr), + (tuple(src_relevant_fields), tuple(src_relevant_fields))) c = cr.fetchone()[0] _logger.debug("ir.translation.cursor: %d entries now in ir.translation, %d common entries with tmp", c1, c)