diff --git a/odoo/tools/translate.py b/odoo/tools/translate.py index e22167bf384..a766adeb2a6 100644 --- a/odoo/tools/translate.py +++ b/odoo/tools/translate.py @@ -1562,17 +1562,19 @@ def _get_translation_upgrade_queries(cr, field): if field.translate is True: query = f""" WITH t AS ( - SELECT res_id, jsonb_object_agg(lang, value) AS value - FROM _ir_translation - WHERE type = 'model' AND name = %s AND state = 'translated' - GROUP BY res_id + SELECT it.res_id as res_id, jsonb_object_agg(it.lang, it.value) AS value, bool_or(imd.noupdate) AS noupdate + FROM _ir_translation it + LEFT JOIN ir_model_data imd + ON imd.model = %s AND imd.res_id = it.res_id + WHERE it.type = 'model' AND it.name = %s AND it.state = 'translated' + GROUP BY it.res_id ) UPDATE {Model._table} m - SET "{field.name}" = t.value || m."{field.name}" + SET "{field.name}" = CASE WHEN t.noupdate THEN m."{field.name}" || t.value ELSE t.value || m."{field.name}" END FROM t WHERE t.res_id = m.id """ - migrate_queries.append(cr.mogrify(query, [translation_name]).decode()) + migrate_queries.append(cr.mogrify(query, [Model._name, translation_name]).decode()) query = "DELETE FROM _ir_translation WHERE type = 'model' AND name = %s" cleanup_queries.append(cr.mogrify(query, [translation_name]).decode()) @@ -1589,27 +1591,29 @@ def _get_translation_upgrade_queries(cr, field): ), t AS ( -- aggregate translations by lang -- - SELECT res_id, jsonb_object_agg(lang, value) AS value + SELECT t0.res_id AS res_id, jsonb_object_agg(t0.lang, t0.value) AS value, bool_or(imd.noupdate) AS noupdate FROM t0 - GROUP BY res_id + LEFT JOIN ir_model_data imd + ON imd.model = %s AND imd.res_id = t0.res_id + GROUP BY t0.res_id ) - SELECT t.res_id, m."{field.name}", t.value + SELECT t.res_id, m."{field.name}", t.value, t.noupdate FROM t JOIN "{Model._table}" m ON t.res_id = m.id - """, [translation_name]) - for id_, old_values, translations in cr.fetchall(): - if not old_values: + """, [translation_name, Model._name]) + for id_, new_translations, translations, noupdate in cr.fetchall(): + if not new_translations: continue - # 'old_values' contain terms possibly updated from PO files during - # the upgrade of modules; prefer those terms over the ones from - # the out-of-date 'translations' dict - src_value = old_values.pop('en_US') + # new_translations contains translations updated from the latest po files + src_value = new_translations.pop('en_US') src_terms = field.get_trans_terms(src_value) - for lang, dst_value in old_values.items(): + for lang, dst_value in new_translations.items(): terms_mapping = translations.setdefault(lang, {}) dst_terms = field.get_trans_terms(dst_value) for src_term, dst_term in zip(src_terms, dst_terms): - if src_term != dst_term: + if src_term == dst_term or noupdate: + terms_mapping.setdefault(src_term, dst_term) + else: terms_mapping[src_term] = dst_term new_values = { lang: field.translate(terms_mapping.get, src_value)