Files
2026-07-11 00:27:43 +02:00

187 lines
6.9 KiB
Python

from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
class TranslationConfig(models.Model):
_name = 'otk.translation.config'
_description = 'Translation Configuration'
_rec_name = 'model_id'
model_id = fields.Many2one(
'ir.model',
string="Model",
required=True,
ondelete='cascade',
domain="[('transient', '=', False)]",
)
active = fields.Boolean(default=True)
has_translatable_fields = fields.Boolean(
compute='_compute_has_translatable_fields',
store=True,
)
translatable_field_ids = fields.Many2many(
'ir.model.fields',
string="Translatable Fields",
compute='_compute_has_translatable_fields',
store=True,
)
server_action_id = fields.Many2one(
'ir.actions.server',
string="Server Action",
readonly=True,
ondelete='set null',
)
@api.constrains('model_id')
def _check_unique_model_id(self):
for record in self:
if record.model_id:
if self.search([('model_id', '=', record.model_id.id), ('id', '!=', record.id)]):
raise ValidationError(_("A configuration already exists for this model."))
@api.depends('model_id')
def _compute_has_translatable_fields(self):
for record in self:
if record.model_id:
translatable_fields = self.env['ir.model.fields'].search([
('model_id', '=', record.model_id.id),
('translate', 'in', ['standard', 'html_translate', 'xml_translate']),
('related', '=', False),
('store', '=', True),
])
record.translatable_field_ids = translatable_fields
record.has_translatable_fields = bool(translatable_fields)
else:
record.translatable_field_ids = False
record.has_translatable_fields = False
@api.model_create_multi
def create(self, vals_list):
records = super().create(vals_list)
records._create_server_actions()
return records
def write(self, vals):
model_changed = 'model_id' in vals
result = super().write(vals)
if 'active' in vals or model_changed:
self._update_server_actions(model_changed=model_changed)
return result
def unlink(self):
self.server_action_id.unlink()
return super().unlink()
def _create_server_actions(self):
"""Create server actions for each configuration."""
for record in self:
if not record.server_action_id and record.model_id:
record._create_single_server_action()
def _create_single_server_action(self):
"""Create a single server action for this configuration."""
self.ensure_one()
if not self.model_id:
return
action_name = _('Bulk translate')
server_action = self.env['ir.actions.server'].sudo().create({
'name': action_name,
'model_id': self.model_id.id,
'binding_model_id': self.model_id.id,
'binding_view_types': 'list',
'state': 'code',
'code': "action = env['otk.translation.config'].action_bulk_translate_generic()",
})
# Create external ID for the server action
action_xml_id = 'bulk_translate_config_action_for_' + self.model_id.model.replace('.', '_')
existing_data = self.env['ir.model.data'].sudo().search([
('module', '=', 'otoolkit_auto_translate_fields'),
('name', '=', action_xml_id),
])
if existing_data:
existing_data.unlink()
self.env['ir.model.data'].sudo().create({
'name': action_xml_id,
'model': 'ir.actions.server',
'module': 'otoolkit_auto_translate_fields',
'res_id': server_action.id,
'noupdate': True,
})
self.server_action_id = server_action
def _update_server_actions(self, model_changed=False):
"""Update server actions when configuration changes."""
for record in self:
# If model changed, delete old action and create new one
if model_changed and record.server_action_id:
record.server_action_id.unlink()
record.server_action_id = False
if record.active and not record.server_action_id:
record._create_single_server_action()
elif not record.active and record.server_action_id:
record.server_action_id.unlink()
record.server_action_id = False
@api.model
def action_bulk_translate_generic(self):
"""Generic action to open bulk translate wizard - called from server actions."""
active_model = self.env.context.get('active_model')
if not active_model:
return {'type': 'ir.actions.act_window_close'}
return {
'type': 'ir.actions.act_window',
'name': _('Bulk translate'),
'res_model': 'otk.translation.bulk.translate',
'view_mode': 'form',
'view_id': self.env.ref('otoolkit_auto_translate_fields.view_bulk_translate_wizard_form').id,
'target': 'new',
}
def action_enable_all_translatable_models(self):
"""Enable bulk translation for all models that have translatable fields."""
# Find all models with translatable fields
translatable_models = self.env['ir.model.fields'].search([
('translate', 'in', ['standard', 'html_translate', 'xml_translate']),
('related', '=', False),
('store', '=', True),
]).mapped('model_id')
# Filter out transient models and already configured models
existing_model_ids = self.search([]).mapped('model_id.id')
models_to_add = translatable_models.filtered(
lambda m: m.id not in existing_model_ids and not m.transient
)
# Create configurations
vals_list = [{'model_id': model.id} for model in models_to_add]
created = self.create(vals_list)
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Bulk Translation Enabled'),
'message': _('%d models have been configured for bulk translation.') % len(created),
'type': 'success',
'sticky': False,
}
}
def action_view_translatable_fields(self):
"""View the translatable fields for this model."""
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'name': _('Translatable Fields'),
'res_model': 'ir.model.fields',
'view_mode': 'list,form',
'domain': [('id', 'in', self.translatable_field_ids.ids)],
'target': 'current',
}