Skip to content

Commit 073c4f9

Browse files
committed
[IMP] base: store explicit field.translate to database
before this commit: | field.translate in orm | ir_model_field.translate in database | | ---------------------- | ------------------------------------ | | False | False | | True | True | | html_translate | True | | xml_translate | True | after this commit: | field.translate in orm | ir_model_field.translate in database | | ---------------------- | ------------------------------------ | | False | NULL | | True | 'standard' | | html_translate | 'html_translate' | | xml_translate | 'xml_translate' | closes #219406 Related: odoo/enterprise#90413 Related: odoo/upgrade#8085 Related: odoo/upgrade-util#296 Signed-off-by: Raphael Collet <[email protected]>
1 parent f23e256 commit 073c4f9

File tree

7 files changed

+42
-11
lines changed

7 files changed

+42
-11
lines changed

addons/web/tests/test_translate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def setUpClass(cls):
1212
'name': 'x_html_test',
1313
'ttype': 'html',
1414
'model_id': cls.category.id,
15-
'translate': True,
15+
'translate': 'html_translate',
1616
})
1717

1818
def test_web_override_translations(self):

odoo/addons/base/models/ir_model.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from odoo.fields import Command, Domain
1818
from odoo.tools import frozendict, reset_cached_properties, split_every, sql, unique, OrderedSet, SQL
1919
from odoo.tools.safe_eval import safe_eval, datetime, dateutil, time
20-
from odoo.tools.translate import _, LazyTranslate
20+
from odoo.tools.translate import FIELD_TRANSLATE, LazyTranslate, _
2121

2222
_lt = LazyTranslate(__name__)
2323
_logger = logging.getLogger(__name__)
@@ -533,7 +533,11 @@ class IrModelFields(models.Model):
533533
required = fields.Boolean()
534534
readonly = fields.Boolean()
535535
index = fields.Boolean(string='Indexed')
536-
translate = fields.Boolean(string='Translatable', help="Whether values for this field can be translated (enables the translation mechanism for that field)")
536+
translate = fields.Selection([
537+
('standard', 'Translate as a whole'),
538+
('html_translate', 'Translate HTML terms'),
539+
('xml_translate', 'Translate XML terms'),
540+
], string='Translatable', help="Whether values for this field can be translated (enables the translation mechanism for that field)")
537541
company_dependent = fields.Boolean(string='Company Dependent', help="Whether values for this field is company dependent", readonly=True)
538542
size = fields.Integer()
539543
state = fields.Selection([('manual', 'Custom Field'), ('base', 'Base Field')], string='Type', default='manual', required=True, readonly=True, index=True)
@@ -993,6 +997,9 @@ def unlink(self):
993997
def create(self, vals_list):
994998
IrModel = self.env['ir.model']
995999
for vals in vals_list:
1000+
if vals.get('translate') and not isinstance(vals['translate'], str):
1001+
_logger.warning("Deprecated since Odoo 19, ir.model.fields.translate becomes Selection, the value should be a string")
1002+
vals['translate'] = 'html_translate' if vals.get('ttype') == 'html' else 'standard'
9961003
if 'model_id' in vals:
9971004
vals['model'] = IrModel.browse(vals['model_id']).model
9981005

@@ -1073,6 +1080,10 @@ def write(self, vals):
10731080
if column_name in vals:
10741081
del vals[column_name]
10751082

1083+
if vals.get('translate') and not isinstance(vals['translate'], str):
1084+
_logger.warning("Deprecated since Odoo 19, ir.model.fields.translate becomes Selection, the value should be a string")
1085+
vals['translate'] = 'html_translate' if vals.get('ttype') == 'html' else 'standard'
1086+
10761087
res = super(IrModelFields, self).write(vals)
10771088

10781089
self.env.flush_all()
@@ -1119,6 +1130,7 @@ def _compute_display_name(self):
11191130

11201131
def _reflect_field_params(self, field, model_id):
11211132
""" Return the values to write to the database for the given field. """
1133+
translate = next(k for k, v in FIELD_TRANSLATE.items() if v == field.translate)
11221134
return {
11231135
'model_id': model_id,
11241136
'model': field.model_name,
@@ -1137,7 +1149,7 @@ def _reflect_field_params(self, field, model_id):
11371149
'required': bool(field.required),
11381150
'selectable': bool(field.search or field.store),
11391151
'size': getattr(field, 'size', None),
1140-
'translate': bool(field.translate),
1152+
'translate': translate,
11411153
'company_dependent': bool(field.company_dependent),
11421154
'relation_field': field.inverse_name if field.type == 'one2many' else None,
11431155
'relation_table': field.relation if field.type == 'many2many' else None,
@@ -1252,7 +1264,10 @@ def _instanciate_attrs(self, field_data):
12521264
'company_dependent': bool(field_data['company_dependent']),
12531265
}
12541266
if field_data['ttype'] in ('char', 'text', 'html'):
1255-
attrs['translate'] = bool(field_data['translate'])
1267+
attrs['translate'] = FIELD_TRANSLATE.get(
1268+
field_data['translate'],
1269+
True
1270+
)
12561271
if field_data['ttype'] == 'char':
12571272
attrs['size'] = field_data['size'] or None
12581273
elif field_data['ttype'] == 'html':

odoo/addons/test_orm/tests/test_schema.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from odoo.fields import Domain
22
from odoo.tests import common
3+
from odoo.tools.translate import FIELD_TRANSLATE
34

45
from odoo.addons.base.models.ir_model import field_xmlid, model_xmlid, selection_xmlid
56

@@ -195,7 +196,7 @@ def test_models_fields(self):
195196
self.assertEqual(ir_field.readonly, bool(field.readonly))
196197
self.assertEqual(ir_field.required, bool(field.required))
197198
self.assertEqual(ir_field.selectable, bool(field.search or field.store))
198-
self.assertEqual(ir_field.translate, bool(field.translate))
199+
self.assertEqual(FIELD_TRANSLATE.get(ir_field.translate or None, True), field.translate)
199200
if field.relational:
200201
self.assertEqual(ir_field.relation, field.comodel_name)
201202
if field.type == 'one2many' and field.store:

odoo/modules/loading.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,8 @@ def load_modules(
377377

378378
if update_module and tools.sql.table_exists(cr, 'ir_model_fields'):
379379
# determine the fields which are currently translated in the database
380-
cr.execute("SELECT model || '.' || name FROM ir_model_fields WHERE translate IS TRUE")
381-
registry._database_translated_fields = {row[0] for row in cr.fetchall()}
380+
cr.execute("SELECT model || '.' || name, translate FROM ir_model_fields WHERE translate IS NOT NULL")
381+
registry._database_translated_fields = dict(cr.fetchall())
382382

383383
# determine the fields which are currently company dependent in the database
384384
if odoo.tools.sql.column_exists(cr, 'ir_model_fields', 'company_dependent'):
@@ -455,7 +455,7 @@ def load_modules(
455455
if update_module:
456456
# set up the registry without the patch for translated fields
457457
database_translated_fields = registry._database_translated_fields
458-
registry._database_translated_fields = set()
458+
registry._database_translated_fields = {}
459459
registry._setup_models__(cr, []) # incremental setup
460460
# determine which translated fields should no longer be translated,
461461
# and make their model fix the database schema

odoo/orm/model_classes.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
frozendict,
2020
sql,
2121
)
22+
from odoo.tools.translate import FIELD_TRANSLATE
2223

2324
if typing.TYPE_CHECKING:
2425
from odoo.api import Environment
@@ -382,9 +383,13 @@ def _setup(model_cls: type[BaseModel], env: Environment):
382383
field._args__['translate'] for field in reversed(fields_) if 'translate' in field._args__
383384
), False)
384385
if not translate:
386+
field_translate = FIELD_TRANSLATE.get(
387+
model_cls.pool._database_translated_fields[f'{model_cls._name}.{name}'],
388+
True
389+
)
385390
# patch the field definition by adding an override
386391
_logger.debug("Patching %s.%s with translate=True", model_cls._name, name)
387-
fields_.append(type(fields_[0])(translate=True))
392+
fields_.append(type(fields_[0])(translate=field_translate))
388393
if f'{model_cls._name}.{name}' in model_cls.pool._database_company_dependent_fields:
389394
# the field is currently company dependent in the database; ensure
390395
# the field is company dependent to avoid converting its column to

odoo/orm/registry.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ def init(self, db_name: str) -> None:
220220

221221
self.models: dict[str, type[BaseModel]] = {} # model name/model instance mapping
222222
self._sql_constraints = set() # type: ignore
223-
self._database_translated_fields: set[str] = set() # names of translated fields in database "{model}.{field_name}"
223+
self._database_translated_fields: dict[str, str] = {} # names and translate function names of translated fields in database {"{model}.{field_name}": "translate_func"}
224224
self._database_company_dependent_fields: set[str] = set() # names of company dependent fields in database
225225
if config['test_enable']:
226226
from odoo.tests.result import OdooTestResult # noqa: PLC0415

odoo/tools/translate.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@
7979

8080
TRANSLATED_ATTRS.update({f't-attf-{attr}' for attr in TRANSLATED_ATTRS})
8181

82+
# {column value of "ir_model_fields"."translate": orm field.translate}
83+
FIELD_TRANSLATE = {
84+
None: False,
85+
'standard': True,
86+
}
87+
88+
8289
def is_translatable_attrib(key):
8390
return key in TRANSLATED_ATTRS or key.endswith('.translate')
8491

@@ -387,6 +394,9 @@ def is_text(term):
387394

388395
xml_translate.term_adapter = xml_term_adapter
389396

397+
FIELD_TRANSLATE['html_translate'] = html_translate
398+
FIELD_TRANSLATE['xml_translate'] = xml_translate
399+
390400

391401
def get_translation(module: str, lang: str, source: str, args: tuple | dict) -> str:
392402
"""Translate and format using a module, language, source text and args."""

0 commit comments

Comments
 (0)