7.9 KiB
Sistema de Traducciones - Guía Completa
Estado Actual
✅ El sistema de traducciones está funcionando correctamente
Todos los addons custom incluyen traducciones para:
- Español (es) - Obligatorio
- Euskera (eu) - Obligatorio
- Catalán (ca), Gallego (gl), Portugués (pt), Francés (fr), Italiano (it) - Opcional
Estructura de Archivos
Cada addon debe tener la siguiente estructura:
addon_name/
├── i18n/
│ ├── es.po # Español (obligatorio)
│ ├── eu.po # Euskera (obligatorio)
│ ├── ca.po # Catalán (opcional)
│ ├── gl.po # Gallego (opcional)
│ ├── pt.po # Portugués (opcional)
│ ├── fr.po # Francés (opcional)
│ ├── it.po # Italiano (opcional)
│ └── addon_name.pot # Template (generado automáticamente)
Reglas Importantes
❌ NO Hacer
NUNCA usar _() en definiciones de campos a nivel de módulo:
# ❌ INCORRECTO - Causa warnings
from odoo import _
class MyModel(models.Model):
_name = 'my.model'
name = fields.Char(string=_("Name")) # ❌ MAL
description = fields.Text(string=_("Description")) # ❌ MAL
Por qué está mal: _() se ejecuta en tiempo de importación del módulo, antes de que el sistema de traducciones esté inicializado, causando warnings.
✅ Hacer
Usar strings literales en definiciones de campos:
# ✅ CORRECTO
from odoo import models, fields
class MyModel(models.Model):
_name = 'my.model'
name = fields.Char(string="Name") # ✅ BIEN
description = fields.Text(string="Description") # ✅ BIEN
Usar _() solo en métodos y código ejecutable:
# ✅ CORRECTO
from odoo import _, models
class MyModel(models.Model):
_name = 'my.model'
def action_confirm(self):
message = _("Order confirmed successfully") # ✅ BIEN
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Success'), # ✅ BIEN
'message': message,
'type': 'success',
}
}
def _compute_display_name(self):
for record in self:
record.display_name = _("Order %s") % record.name # ✅ BIEN
Cómo Generar/Actualizar Traducciones
1. Exportar Términos Traducibles
NO HACER:
# Exportar términos del addon
docker-compose exec odoo odoo \
--addons-path=/mnt/extra-addons \
--i18n-export=/tmp/addon_name.pot \
--modules=addon_name \
--db=odoo \
--stop-after-init
De alguna forma, exporta todas las cadenas de Odoo.
PEDIR AL USUARIO QUE GENERE EL POT DESDE LA UI DE ODOO
# Copiar el archivo generado
docker-compose cp odoo:/tmp/addon_name.pot ./addon_name/i18n/
2. Actualizar Archivos .po Existentes
no usar msmerge, corrompe el po. Usa polib.
3. Traducir Términos Nuevos
Editar los archivos .po y completar las traducciones:
#: models/my_model.py:25
msgid "Order confirmed successfully"
msgstr "Pedido confirmado correctamente" # Español
#: models/my_model.py:30
msgid "Success"
msgstr "Éxito"
4. Cargar Traducciones en Odoo
# Actualizar addon con nuevas traducciones
docker-compose exec odoo odoo -d odoo -u addon_name --stop-after-init
# O reiniciar Odoo para que cargue los cambios
docker-compose restart odoo
Formato de Archivos .po
Cabecera Requerida
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * addon_name
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-02-12 10:00+0000\n"
"PO-Revision-Date: 2026-02-12 10:00+0000\n"
"Last-Translator: Your Name <your.email@example.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
Campos Traducibles
Odoo automáticamente detecta y exporta:
- String en definiciones de campos:
fields.Char(string="Name") - Help text:
fields.Char(help="Enter the product name") - Selection options:
fields.Selection([('draft', 'Draft'), ('done', 'Done')]) - Texto en vistas XML:
<label string="Customer Name"/> - Botones en vistas:
<button string="Confirm"/> - Mensajes en código:
_("Message text") - Excepciones:
raise ValidationError(_("Invalid value"))
Verificación
Comprobar que las Traducciones Funcionan
-
Activar el idioma en Odoo:
- Settings > Translations > Load a Translation
- Seleccionar el idioma (ej: Español)
-
Cambiar idioma de usuario:
- Settings > Users > [Usuario]
- Language: Español
-
Verificar en la interfaz:
- Abrir el módulo
- Verificar que los textos aparecen traducidos
Logs de Carga
Al actualizar el módulo, verificar en logs:
docker-compose logs odoo | grep "loading translation"
Debe mostrar:
odoo.modules.loading: loading translation file for language 'es': addon_name/i18n/es.po
odoo.modules.loading: loading translation file for language 'eu': addon_name/i18n/eu.po
Addons con Traducciones Completas
Addons Custom
| Addon | es | eu | Otros |
|---|---|---|---|
| account_invoice_triple_discount_readonly | ✅ | ✅ | - |
| product_price_category_supplier | ✅ | ✅ | - |
| product_sale_price_from_pricelist | ✅ | - | - |
| website_sale_aplicoop | ✅ | ✅ | ca, gl, pt, fr, it |
Addons OCA
Los addons OCA ya incluyen traducciones en múltiples idiomas.
Troubleshooting
Warning: "_() called at import time"
Síntoma:
WARNING: _() called at import time at module.path:line
Causa: _() usado en definición de campo a nivel de módulo
Solución: Eliminar _() de la definición del campo:
# Cambiar:
name = fields.Char(string=_("Name"))
# Por:
name = fields.Char(string="Name")
Traducciones No Aparecen
Posibles causas:
- Archivo .po mal formado: Verificar encoding UTF-8
- Módulo no actualizado:
docker-compose exec odoo odoo -d odoo -u addon_name --stop-after-init - Idioma no activado: Settings > Translations > Load Translation
- Usuario con idioma incorrecto: Verificar preferencias de usuario
- Cache: Reiniciar Odoo:
docker-compose restart odoo
Caracteres Especiales
Usar escape correcto en .po:
# Comillas
msgstr "Haga clic en \"Confirmar\""
# Saltos de línea
msgstr "Primera línea\n"
"Segunda línea"
# Caracteres especiales (á, é, í, ó, ú, ñ, ç)
# Usar directamente, el archivo debe ser UTF-8
msgstr "Configuración"
Herramientas Útiles
Editores de .po
- Poedit: https://poedit.net/ (GUI, recomendado)
- VS Code: Con extensión "gettext" para syntax highlighting
- Lokalize: Editor KDE para traducciones
Comandos Útiles
# Verificar formato de archivo .po
msgfmt -c -v -o /dev/null addon_name/i18n/es.po
# Estadísticas de traducción
msgfmt --statistics addon_name/i18n/es.po
# Extraer solo términos sin traducir
msgattrib --untranslated addon_name/i18n/es.po
Mejores Prácticas
- ✅ Mantener es.po y eu.po siempre actualizados
- ✅ Usar términos consistentes en todo el proyecto
- ✅ Incluir contexto en comentarios cuando sea necesario
- ✅ Verificar traducciones antes de commit
- ✅ Nunca usar
_()en definiciones de campos - ✅ Usar encoding UTF-8 en todos los archivos .po
- ✅ Generar .pot después de cambios importantes
- ✅ Documentar términos técnicos específicos del dominio
Referencias
- Odoo Translation Guidelines: https://www.odoo.com/documentation/18.0/developer/reference/frontend/translations.html
- GNU gettext Manual: https://www.gnu.org/software/gettext/manual/
- OCA Translation Guidelines: https://github.com/OCA/maintainer-tools/wiki/Translations
Última Actualización: 2026-02-12