[FIX] translate: upgrade interraction with l10n_multilang
When upgrading a database with `l10n_multilang` installed, the
translations kept were not the right ones.
Here is the process that was executed during the upgrade:
* `base` is loaded: registry is loaded with `translate=True`, which
calls `convert_column_translatable`. This has the effect of setting
the value of the field to `{'en_US': name}`, with only that language
installed.
* `l10n_multilang` is loaded: the function `lang_install` is extended to
copy the translations of the templates on the instanciated records.
* `l10n_*` is loaded: the translation values are loaded from the `.po`
files. `lang_install` is called after the loading on the templates,
copying the value on the records. The value on the records is now
something like `{'en_US': name, 'fr_BE': nom, 'nl_BE': naam}`.
* `base/end-migrate` is executed: it copies the values coming from
`ir_translation`, without overriding the values that are already on
the record because of the order of the `||` operator.
This means that any value inputed by the user[^1] will be overriden by
the value in the `.po` files.
opw-3175383
closes odoo/odoo#115254
X-original-commit: 5d46cdee878d752b9a61a74762a8710be0890e9d
Signed-off-by: Christophe Simonis <chs@odoo.com>
Co-authored-by: william-andre <wan@odoo.com>
Co-authored-by: HydrionBurst <cwg@odoo.com>
This commit is contained in:
committed by
Chong Wang (cwg)
co-authored by
william-andre
parent
5f6c758adb
commit
4feb7ba3c8
+22
-18
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user