# 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:**

```python
# ❌ 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:**

```python
# ✅ 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:**

```python
# ✅ 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:
```bash
# 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:

```po
#: 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

```bash
# 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

```po
# 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:

1. **String en definiciones de campos**: `fields.Char(string="Name")`
2. **Help text**: `fields.Char(help="Enter the product name")`
3. **Selection options**: `fields.Selection([('draft', 'Draft'), ('done', 'Done')])`
4. **Texto en vistas XML**: `<label string="Customer Name"/>`
5. **Botones en vistas**: `<button string="Confirm"/>`
6. **Mensajes en código**: `_("Message text")`
7. **Excepciones**: `raise ValidationError(_("Invalid value"))`

## Verificación

### Comprobar que las Traducciones Funcionan

1. **Activar el idioma en Odoo**:
   - Settings > Translations > Load a Translation
   - Seleccionar el idioma (ej: Español)

2. **Cambiar idioma de usuario**:
   - Settings > Users > [Usuario]
   - Language: Español

3. **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:

```bash
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:
```python
# Cambiar:
name = fields.Char(string=_("Name"))
# Por:
name = fields.Char(string="Name")
```

### Traducciones No Aparecen

**Posibles causas**:

1. **Archivo .po mal formado**: Verificar encoding UTF-8
2. **Módulo no actualizado**: `docker-compose exec odoo odoo -d odoo -u addon_name --stop-after-init`
3. **Idioma no activado**: Settings > Translations > Load Translation
4. **Usuario con idioma incorrecto**: Verificar preferencias de usuario
5. **Cache**: Reiniciar Odoo: `docker-compose restart odoo`

### Caracteres Especiales

Usar escape correcto en .po:

```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

```bash
# 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

1. ✅ Mantener es.po y eu.po siempre actualizados
2. ✅ Usar términos consistentes en todo el proyecto
3. ✅ Incluir contexto en comentarios cuando sea necesario
4. ✅ Verificar traducciones antes de commit
5. ✅ Nunca usar `_()` en definiciones de campos
6. ✅ Usar encoding UTF-8 en todos los archivos .po
7. ✅ Generar .pot después de cambios importantes
8. ✅ 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
