Skip to content

Commit 4e4a801

Browse files
committed
[FIX] Preserve all translated fields on v16 migration
Currently, the upgrade process preserves translations only for Odoo CE+EE fields. However, databases usually have more modules (or even custom fields) and those translations get lost when upgrading to Odoo 16. With this script, all translated fields will inherit their translations in all languages. Since it is executed in the `pre` phase of `base`, it should be able to still find the `ir_translation` table. @moduon MT-7120
1 parent c8c1a6e commit 4e4a801

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed
+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""Store ir.translation records in jsonb fields."""
2+
3+
import logging
4+
5+
from psycopg2.extras import Json
6+
from psycopg2.sql import SQL, Identifier
7+
8+
from odoo.upgrade import util
9+
10+
_logger = logging.getLogger(__name__)
11+
12+
13+
def migrate(cr, version):
14+
already_converted = set()
15+
missing_tables = set()
16+
missing_columns = set()
17+
cr.execute(
18+
"""
19+
SELECT name, res_id, src, jsonb_agg(lang) AS langs, jsonb_agg(value) AS values
20+
FROM ir_translation
21+
WHERE res_id != 0 AND type = 'model' AND state in ('translated', 'to_translate')
22+
GROUP BY name, res_id, src
23+
ORDER BY src IS NOT NULL
24+
"""
25+
)
26+
for name, res_id, src, langs, values in cr.fetchall():
27+
# Build a dict with all translations
28+
all_values = dict(zip(langs, values, strict=True), en_US=src)
29+
if not all_values["en_US"]:
30+
all_values["en_US"] = all_values[langs[0]]
31+
# Find the translation target table and column
32+
model, field = name.split(",")
33+
table = util.table_of_model(cr, model)
34+
# Skip early if the translation is no longer usable
35+
if not util.table_exists(cr, table):
36+
missing_tables.add(table)
37+
continue
38+
if not util.column_exists(cr, table, field):
39+
missing_columns.add(f"{table}.{field}")
40+
continue
41+
# Make sure the field is translatable in JSONB format (noop if done already)
42+
if (model, field) not in already_converted:
43+
util.convert_field_to_translatable(cr, model, field)
44+
already_converted.add((model, field))
45+
# Store updated translation
46+
cr.execute(
47+
SQL("UPDATE {table} SET {field} = %s WHERE id = %s").format(
48+
table=Identifier(table),
49+
field=Identifier(field),
50+
),
51+
(Json(all_values), res_id),
52+
)
53+
# Log missing tables and columns
54+
if missing_tables:
55+
_logger.warning(
56+
"Couldn't recover translation for these missing tables: %s",
57+
", ".join(sorted(missing_tables)),
58+
)
59+
if missing_columns:
60+
_logger.warning(
61+
"Couldn't recover translation for these missing columns: %s",
62+
", ".join(sorted(missing_columns)),
63+
)

0 commit comments

Comments
 (0)