erick:~$ cat bienvenido.md
Inicio chevron_right Configuración chevron_right Prompt para actualizar el idioma de ERPNext a español de manera completa

Prompt para actualizar el idioma de ERPNext a español de manera completa

ERPNext Configuración 2 jun 2026 • 5 min de lectura

Contexto de Negocio e Implementación

Aunque ERPNext soporta múltiples idiomas de manera nativa, la traducción al español en ciertas versiones puede quedar incompleta (especialmente en módulos de facturación avanzada, manufactura, o cuando desarrollamos DocTypes personalizados). Los textos en inglés mezclados con español reducen la calidad de la experiencia del usuario final y confunden a los operadores.

El método tradicional requiere buscar manualmente cada cadena de texto y traducirla en el portal oficial de traducción de Frappe o editar archivos .csv en cada app. Con este prompt, puedes generar archivos de traducción CSV de forma masiva o parches de base de datos directos para las cadenas críticas que aún salen en inglés.


terminal Prompt de Automatización (.md)

Actúa como un Desarrollador Senior de Frappe e Ingeniero de Localización de software.

Objetivo

Localizar, traducir e integrar de forma masiva, robusta y persistente todas las cadenas de texto (UI, alertas, reportes, dashboards, onboarding y registros de base de datos) del entorno ERPNext v16 al español peruano (es-PE), encapsulando todo en una aplicación personalizada para que los cambios no se pierdan al actualizar el core o recrear los contenedores Docker.

Parámetros de Entrada

  • Nombre del Sitio Local: [Ej: frappe-docker]
  • Nombre de la App Personalizada: [Ej: erpnext_peru]

Instrucciones de Ejecución (Flujo Autónomo de un Solo Paso)

1. Inicialización y Vinculación de la App

  • Detectar la ruta del bench. Si la app personalizada no existe, crearla (bench new-app) e instalarla en el sitio (bench --site [sitio] install-app).
  • IMPORTANTE: Registrar la app añadiendo su nombre al final del archivo físico sites/apps.txt del bench. Sin esto, el motor de traducción del Desk en el frontend ignorará silenciosamente los archivos .mo de la app.
  • En entornos Docker, añadir la ruta de assets públicos de la app personalizada al volumen del contenedor frontend en el docker-compose.yml (ej: ./apps/erpnext_peru/erpnext_peru/public:/home/frappe/frappe-bench/assets/erpnext_peru) para evitar errores 404/MIME-type, y reiniciar los contenedores (docker compose down && docker compose up -d).

2. Traducción Masiva y Pruning del PO

  • Crear o actualizar apps/{nombre_app}/{nombre_app}/locale/es.po.
  • Extraer las cadenas vacías o sin traducir de los archivos .po y de las plantillas .pot de frappe y erpnext.
  • Utilizar un script de traducción por lotes (lotes de 40) con la API de traducción, aplicando un delay progresivo (1.5s) y reintentos para evitar errores HTTP 429.
  • Pautas de traducción para Perú (es-PE):
    • Usar tuteo estándar (no voseo: ej: “Guarda”, “Crea”, “Configura”, “Ingresa”).
    • Traducir términos específicos: “Warehouse” -> “Almacén”, “Delivery Note” -> “Guía de Remisión”.
    • Respetar y no traducir comandos CLI, variables o términos técnicos.
  • Limpieza de duplicados: Eliminar del archivo .po de la custom app las entradas idénticas al original o que ya estén correctamente traducidas en el core de Frappe/ERPNext para evitar que pisen con cadenas vacías traducciones correctas del core.

3. Traducción de Registros de Base de Datos (Data Records)

  • Traducir registros y valores estándar de configuración que se guardan en la base de datos (por ejemplo, tipos de proyecto, tipos de actividades, modos de pago, tipos de oportunidad, géneros, designaciones de cargos) ingresando registros en el DocType Translation.
  • Cadenas a insertar/actualizar obligatoriamente en tabTranslation (idioma: ‘es’):
    • Project Type: “Internal” -> “Interno”, “External” -> “Externo”, “Other” -> “Otro”
    • Activity Type: “Planning” -> “Planificación”, “Research” -> “Investigación”, “Proposal Writing” -> “Redacción de Propuestas”, “Execution” -> “Ejecución”, “Communication” -> “Comunicación”
    • Mode of Payment: “Cheque” -> “Cheque”, “Cash” -> “Efectivo”, “Credit Card” -> “Tarjeta de Crédito”, “Wire Transfer” -> “Transferencia Bancaria”, “Bank Draft” -> “Cheque de Gerencia”
    • Opportunity Type: “Maintenance” -> “Mantenimiento”, “Support” -> “Soporte”, “Sales” -> “Ventas”
    • Gender: “Male” -> “Masculino”, “Female” -> “Femenino”, “Transgender” -> “Transgénero”, “Genderqueer” -> “Género no binario”, “Non-Conforming” -> “No conforme”, “Prefer not to say” -> “Prefiero no decirlo”
    • Designations: “Accountant” -> “Contador/a”, “Designer” -> “Diseñador/a”, “Engineer” -> “Ingeniero/a”, “Manager” -> “Gerente”, “Software Developer” -> “Desarrollador/a de Software”, etc.
    • Enlaces de Workspace: “Buying Settings” -> “Configuración de Compras”
    • Descripciones largas: “Warn or stop if Item rate is changed in Purchase Invoice or Purchase Receipt generated from a Purchase Order.” -> “Advertir o detener si se cambia la tarifa del artículo en la factura de compra o el recibo de compra generado a partir de una orden de compra.”
  • Configurar fixtures en el archivo hooks.py de la app personalizada para exportar y persistir tanto el DocType Translation filtrado por language: es como el DocType Property Setter que marca estos DocTypes con translated_doctype = 1:
    fixtures = [
        {
            "doctype": "Translation",
            "filters": [
                ["language", "=", "es"]
            ]
        },
        {
            "doctype": "Property Setter",
            "filters": [
                ["doc_type", "in", ["Project Type", "Activity Type", "Project Template", "Mode of Payment", "Opportunity Type", "Gender", "Designation"]],
                ["property", "=", "translated_doctype"]
            ]
        }
    ]
  • Ejecutar bench --site [sitio] export-fixtures para almacenar los registros en fixtures/translation.json y fixtures/property_setter.json garantizando persistencia absoluta.

4. Parcheo Client-Side de Widgets Dinámicos y Vistas de Lista

  • Dado que los enlaces de los Workspaces y Shortcuts cargan valores de la base de datos directamente en el Desk sin traducirlos en el frontend, y que la columna identificadora principal en las vistas de lista no ejecuta la traducción automáticamente, se debe habilitar app_include_js en hooks.py apuntando a un archivo JS (ej: public/js/erpnext_peru.js).
  • En este script de JavaScript:
    • Interceptar el generador de widgets (frappe.widget.make_widget para “links” y “shortcut”) para traducir dinámicamente las etiquetas en tiempo de renderizado usando la función __().
    • Interceptar frappe.views.ListView.prototype.get_subject_text de manera que si frappe.boot.translated_doctypes contiene el doctype de la lista, devuelva el valor traducido con __() en la interfaz de usuario.

5. Compilación e Invalidación de Caché de Redis

  • Compilar los archivos de traducción .po a .mo usando babel en el entorno virtual del bench.
  • Ejecutar bench --site [sitio] clear-cache.
  • IMPORTANTE: Vaciar completamente el caché de Redis ejecutando redis-cli FLUSHALL (en el contenedor redis-cache) para forzar la reconstrucción de las estructuras merged_translations y bootinfo en el frontend.

6. Verificación y Validación Automatizada

  • Configurar en la base de datos el idioma del sistema y del usuario Administrator a ‘es’.

  • Correr una prueba automática con Playwright que inicie sesión, verifique el Desk y compruebe que no existan errores de red (404), errores de consola JS, y que funciones clave de window.__() y window.frappe.boot retornen los valores traducidos correctamente.


Cómo Cargar las Traducciones en tu App Personalizada de Forma Local

Una vez que tu agente complete la generación del archivo de traducción dentro de la app personalizada, la estructura del bench se verá de la siguiente forma según el sistema de traducción utilizado:

Si usa Gettext (Recomendado en v16)

frappe-bench/
└── apps/
    ├── erpnext/ (Core - Intacto)
    ├── frappe/  (Core - Intacto)
    └── mi_app_personalizada/
        └── mi_app_personalizada/
            └── locale/
                └── es.po  <-- Tus traducciones personalizadas viven aquí

Si usa el sistema legado (CSV)

frappe-bench/
└── apps/
    ├── erpnext/ (Core - Intacto)
    ├── frappe/  (Core - Intacto)
    └── mi_app_personalizada/
        └── mi_app_personalizada/
            └── translations/
                └── es.csv  <-- Tus traducciones personalizadas viven aquí

Para aplicar los cambios y limpiar el estado de sesión del navegador ejecuta:

# Registrar la app personalizada al final de sites/apps.txt del bench
echo "erpnext_peru" >> sites/apps.txt

# Si usas Gettext (.po), compila con:
bench --site frappe-docker compile-translations

# Exportar las fixtures (Traducciones de base de datos y Property Setters):
bench --site frappe-docker export-fixtures

# Limpiar caché de la aplicación:
bench --site frappe-docker clear-cache

# Vaciar Redis (dentro del contenedor redis-cache)
redis-cli FLUSHALL