diff --git a/odoo/models.py b/odoo/models.py index 783a3b09cff..ce1b41d4134 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -2728,6 +2728,17 @@ class BaseModel(metaclass=MetaModel): for field in klass._field_definitions: definitions[field.name].append(field) for name, fields_ in definitions.items(): + if f'{cls._name}.{name}' in cls.pool._database_translated_fields: + # the field is currently translated in the database; ensure the + # field is translated to avoid converting its column to varchar + # and losing data + translate = next(( + field.args['translate'] for field in reversed(fields_) if 'translate' in field.args + ), False) + if not translate: + # patch the field definition by adding an override + _logger.debug("Patching %s.%s with translate=True", cls._name, name) + fields_.append(fields_[0].new(translate=True)) if len(fields_) == 1 and fields_[0]._direct and fields_[0].model_name == cls._name: cls._fields[name] = fields_[0] else: diff --git a/odoo/modules/loading.py b/odoo/modules/loading.py index 33b1a69fba9..e805a1781ab 100644 --- a/odoo/modules/loading.py +++ b/odoo/modules/loading.py @@ -411,6 +411,11 @@ def load_modules(registry, force_demo=False, status=None, update_module=False): _logger.critical('module base cannot be loaded! (hint: verify addons-path)') raise ImportError('Module `base` cannot be loaded! (hint: verify addons-path)') + if update_module and odoo.tools.table_exists(cr, 'ir_model_fields'): + # determine the fields which are currently translated in the database + cr.execute("SELECT model || '.' || name FROM ir_model_fields WHERE translate IS TRUE") + registry._database_translated_fields = {row[0] for row in cr.fetchall()} + # processed_modules: for cleanup step after install # loaded_modules: to avoid double loading report = registry._assertion_report @@ -477,6 +482,23 @@ def load_modules(registry, force_demo=False, status=None, update_module=False): ['to install'], force, status, report, loaded_modules, update_module, models_to_check) + if update_module: + # set up the registry without the patch for translated fields + database_translated_fields = registry._database_translated_fields + registry._database_translated_fields = () + registry.setup_models(cr) + # determine which translated fields should no longer be translated, + # and make their model fix the database schema + models_to_untranslate = set() + for full_name in database_translated_fields: + model_name, field_name = full_name.rsplit('.', 1) + if model_name in registry: + field = registry[model_name]._fields.get(field_name) + if field and not field.translate: + _logger.debug("Making field %s non-translated", field) + models_to_untranslate.add(model_name) + registry.init_models(cr, list(models_to_untranslate), {'models_to_check': True}) + registry.loaded = True registry.setup_models(cr) diff --git a/odoo/modules/registry.py b/odoo/modules/registry.py index be0cc51b3bd..61e5da4973c 100644 --- a/odoo/modules/registry.py +++ b/odoo/modules/registry.py @@ -113,6 +113,7 @@ class Registry(Mapping): self.models = {} # model name/model instance mapping self._sql_constraints = set() self._init = True + self._database_translated_fields = () # names of translated fields in database self._assertion_report = odoo.tests.runner.OdooTestResult() self._fields_by_model = None self._ordinary_tables = None