Odoo · i18n · Localización
El código de un módulo Odoo se escribe en inglés por convención, pero los usuarios finales casi nunca trabajan en inglés. La traducción no es un extra de última hora: es un flujo de trabajo con sus propias herramientas, y hacerlo bien desde el principio ahorra horas de re-exportar ficheros .po a mano.
La base de todo
Código en inglés, marcado para traducir
Cualquier string visible por el usuario (labels, mensajes de error, nombres de campo) debe escribirse en inglés en el código y envolverse para que el motor de traducción de Odoo (basado en gettext) lo detecte. En Python es la función _(); en las vistas XML, los atributos traducibles se detectan automáticamente.
# models/mi_modelo.py
from odoo import models, fields, api
from odoo.exceptions import ValidationError
class MiModelo(models.Model):
_name = "mi.modelo"
_description = "Mi Modelo"
name = fields.Char(string="Name", required=True)
@api.constrains("name")
def _check_name(self):
for record in self:
if len(record.name) < 3:
raise ValidationError(_("The name must have at least 3 characters."))
_() rompe la extracción automática (_(f"Error: {valor}")). Usa el formato con %s o .format() pasado como argumento de _(): _("Error: %s", valor).
Generar la plantilla
El fichero .pot: plantilla de traducción
El .pot (Portable Object Template) es la plantilla con todos los strings traducibles del módulo, sin traducciones todavía. Se genera exportando desde la propia interfaz de Odoo o vía línea de comandos.
# Generar el .pot desde la CLI
odoo-bin -d mi_base_datos --i18n-export=i18n/mi_modulo.pot -m mi_modulo --stop-after-init
Este fichero se guarda en mi_modulo/i18n/mi_modulo.pot y se versiona en git: es la fuente de verdad de qué hay que traducir, y cualquier traductor humano parte de ahí para crear el .po de su idioma.
Idioma por idioma
Ficheros .po: una traducción por idioma
Cada idioma tiene su propio .po (es.po, es_MX.po, fr.po...), con el mismo nombre de fichero que el .pot pero con el código de idioma. Odoo carga automáticamente estos ficheros si están dentro de la carpeta i18n/ del módulo, sin necesidad de declararlos en el manifest.
# i18n/es.po (extracto)
#. module: mi_modulo
#: model:ir.model.fields,field_description:mi_modulo.field_mi_modelo__name
msgid "Name"
msgstr "Nombre"
#. module: mi_modulo
#: code:addons/mi_modulo/models/mi_modelo.py:0
msgid "The name must have at least 3 characters."
msgstr "El nombre debe tener al menos 3 caracteres."
| Fichero | Contiene | Se versiona en git |
|---|---|---|
i18n/mi_modulo.pot | Plantilla, strings sin traducir | Sí |
i18n/es.po | Traducciones al español (España) | Sí |
i18n/es_MX.po | Variante para español de México | Sí, si aplica |
El día a día
Flujo de trabajo: exportar, traducir, importar
- Exportar: Ajustes → Traducciones → Exportar traducción, seleccionando el módulo y el idioma. Genera un
.pocon los strings actuales, ya traducidos si los hubiera y vacíos si son nuevos. - Traducir: editar el
.pocon un editor dedicado (Poedit, Weblate) o directamente en texto plano, respetando el formatomsgid/msgstr. - Importar: Ajustes → Traducciones → Importar, o vía CLI con
--i18n-overwritepara sobrescribir traducciones existentes en una actualización.
# Importar traducciones desde CLI (útil en despliegues automatizados)
odoo-bin -d mi_base_datos -l es_ES --i18n-import=i18n/es.po -m mi_modulo --stop-after-init
.pot y fusiona los cambios en los .po existentes (herramientas como msgmerge hacen esto sin perder traducciones ya hechas).
Resumen
Traducir un módulo Odoo bien es cuestión de disciplina: código en inglés envuelto en _(), un .pot como plantilla versionada, un .po por idioma también versionado, y un flujo de exportar/traducir/importar que se repite cada vez que el módulo gana strings nuevos.