PTC

¿Las traducciones de tu plugin de WordPress no aparecen? Soluciona las traducciones que faltan

¿Faltan traducciones tras una ejecución de PTC? Tres comprobaciones encuentran casi todas las causas. Compruebe que la cadena llegó a PTC, que el nombre del archivo .mo coincide con lo que WordPress espera y que el dominio de texto es coherente en todo su código. Esta guía recorre cada comprobación en el orden en que debe realizarlas.

El mismo orden de diagnóstico funciona tanto si tradujo con PTC (Private Translation Cloud), GlotPress o cualquier otra herramienta basada en gettext. Los modos de fallo son inherentes a la canalización de i18n de WordPress, no a ningún traductor en particular.

Confirme que la cadena llegó a PTC

La primera pregunta es si la cadena está en su proyecto de PTC. Si una cadena no se extrajo a su archivo .pot, PTC nunca la vio. El archivo .po no tiene ninguna traducción para ella. El plugin en ejecución muestra el respaldo del idioma de origen.

Cómo comprobarlo:

  1. Abra la cadena afectada en el plugin en ejecución y copie su texto exacto.
  2. Vaya a su panel de PTC, abra la pestaña Translations y busque la cadena.
  3. Si no está ahí, PTC nunca la recibió.

A continuación, tres causas comunes.

Causa 1: la cadena falta en su archivo POT

wp i18n make-pot solo extrae cadenas que están dentro de las funciones de i18n reconocidas. Es decir, __(), _e(), _n(), _x() y las variantes escapadas, con el dominio de texto correcto. Las cadenas en el dominio equivocado se omiten. Las cadenas codificadas a mano fuera de una función de i18n se omiten.

Vuelva a ejecutar la extracción y verifique que la cadena ahora está en el .pot:

wp i18n make-pot . languages/my-plugin.pot --domain=my-plugin
grep "Save Changes" languages/my-plugin.pot

Si grep devuelve la cadena con un msgid, la extracción funciona. Vuelva a subir el nuevo .pot a PTC y vuelva a traducir. Si grep no devuelve nada, la cadena está codificada a mano y no está envuelta en __(). Ese es su error. Envuelva la cadena y vuelva a extraer.

Causa 2: el texto no está envuelto en una función gettext

Cada cadena traducible de su código necesita un envoltorio. Use __(), esc_html__(), _e(), _n() o _x() con el dominio de texto correcto:

__( 'Hello, world!', 'your-plugin' );

Causa 3: las cadenas de JavaScript no se marcaron como traducibles

Si su plugin incluye texto traducible en JavaScript:

  1. En el panel de PTC, vaya a Settings > Monitored Files.
  2. Edite el archivo de recursos correspondiente y active "Is this a WordPress project with localizable JavaScript?"

Esto indica a PTC que analice los archivos de JavaScript en busca de cadenas traducibles. PTC regenera las traducciones y abre un nuevo merge request con los archivos actualizados.

Luego asegúrese de que WordPress sepa dónde cargar los archivos de traducción .json que PTC produjo. Llame a wp_set_script_translations() con la ruta correcta:

// For plugins
wp_set_script_translations(
    'script-handle',
    'text-domain',
    plugin_dir_path( __FILE__ ) . 'languages'
);

// For themes
wp_set_script_translations(
    'script-handle',
    'text-domain',
    get_template_directory() . '/languages'
);

Esto indica a WordPress que cargue los archivos .json desde la carpeta de su plugin o tema.

Confirme que WordPress está cargando su archivo .mo

Si la cadena está en PTC y el archivo .mo existe en el directorio languages/ de su plugin, pero el plugin renderizado sigue mostrando inglés, WordPress no está cargando el .mo.

Diagnóstico 1: ¿está la configuración regional del sitio definida correctamente? Vaya a Settings > General > Site Language en wp-admin y confirme que coincide con su idioma de destino. Por ejemplo, defínalo como "Espanol" para probar el español. Si el sitio está en inglés, su .mo en español nunca se cargará. Esto no es un error.

Diagnóstico 2: ¿se está ejecutando realmente load_plugin_textdomain()? Agregue una línea de depuración temporal:

add_action( 'init', function() {
    $loaded = load_plugin_textdomain(
        'my-plugin',
        false,
        dirname( plugin_basename( __FILE__ ) ) . '/languages'
    );
    error_log( 'my-plugin textdomain loaded: ' . var_export( $loaded, true ) );
} );

Recargue una página y revise su registro de errores de PHP. loaded: true significa que WordPress encontró y cargó un archivo .mo para la configuración regional actual. loaded: false significa que no lo hizo. La causa suele ser una discrepancia en el nombre del archivo (consulte la siguiente sección) o una ruta de directorio incorrecta.

Diagnóstico 3: ¿es correcto el momento del hook? load_plugin_textdomain() debe ejecutarse en el hook init. Ese es el hook canónico para que las traducciones se apliquen a las cadenas que se imprimen durante el procesamiento normal de la solicitud.

Diagnóstico 4: ¿están las traducciones de la comunidad sobrescribiendo sus archivos incluidos? De forma predeterminada, WordPress prioriza los archivos de traducción almacenados en /wp-content/languages/. Si su plugin o tema tiene traducciones aportadas por la comunidad en WordPress.org, esos archivos pueden sobrescribir los archivos .mo incluidos con su proyecto. Para evitarlo, use el filtro load_textdomain_mofile para forzar la carga de la ruta de su archivo incluido antes de que WordPress consulte el directorio global. Los proyectos con varios dominios de texto (un plugin que integra otro plugin) necesitan cargar cada dominio por separado. Cada dominio necesita su propia llamada a load_plugin_textdomain() o load_theme_textdomain().

Asegúrese de que el nombre del archivo MO coincide con el patrón de búsqueda de WordPress

La búsqueda de archivos .mo de WordPress sigue una convención de nombres estricta. Con un solo carácter de diferencia, WordPress recurre silenciosamente al inglés.

La convención depende de dónde coloque el archivo:

Ubicación Patrón Ejemplo
/languages/ del plugin {text-domain}-{locale}.mo my-plugin-de_DE.mo
/languages/ del tema {locale}.mo de_DE.mo
Directorio global (/wp-content/languages/...) {text-domain}-{locale}.mo my-theme-de_DE.mo

Algunos ejemplos resueltos:

  • my-plugin-es_ES.mo para español (España)
  • my-plugin-fr_FR.mo para francés (Francia)
  • my-plugin-pt_BR.mo para portugués (Brasil)
  • my-plugin-zh_CN.mo para chino simplificado
  • my-plugin-ja.mo para japonés (algunas configuraciones regionales no tienen sufijo de región)

Errores comunes:

  • Prefijo de dominio de texto incorrecto. Si el encabezado Text Domain de su plugin es my-plugin pero el .mo se llama myplugin-es_ES.mo (sin guion), WordPress no lo encontrará. El prefijo debe coincidir exactamente con el valor de Text Domain.
  • Código de configuración regional incorrecto. es.mo en lugar de es_ES.mo. WordPress usa códigos de configuración regional con región. es_ES, es_MX y es_AR son archivos diferentes. Un código de idioma a secas solo funciona cuando no existe ningún archivo regional.
  • Guion frente a guion bajo. Los códigos de configuración regional usan guion bajo (es_ES), nunca guion (es-ES). Esto hace tropezar a los desarrolladores que copian códigos de configuración regional de los encabezados Accept-Language del navegador o de fuentes BCP 47, donde el guion es el estándar.
  • Directorio incorrecto. El encabezado Domain Path debe apuntar al directorio que contiene sus archivos .mo. Si Domain Path es /languages y sus archivos .mo están en /lang/, WordPress no los encontrará.

Compruébelo enumerando los archivos que PTC produjo frente a la configuración regional que usa su sitio:

ls plugins/my-plugin/languages/
# my-plugin-es_ES.mo
# my-plugin-es_ES.po
# my-plugin-fr_FR.mo
# my-plugin-fr_FR.po

Si los nombres parecen correctos pero las traducciones siguen sin cargarse, ejecute el diagnóstico de load_plugin_textdomain() anterior para confirmar que WordPress encuentra el directorio.

Compruebe que su dominio de texto es coherente en todo su código

Este es el asesino silencioso. Cada llamada a __(), _e(), _n(), _x() en su código pasa un dominio de texto como su último argumento. Si aunque sea una sola llamada pasa el dominio equivocado, esa única cadena no se traducirá. Todas las demás cadenas del plugin funcionarán bien.

// Correct - matches the plugin's Text Domain
$correct = __( 'Save Changes', 'my-plugin' );

// Wrong - text domain typo; this string is never translated
$wrong = __( 'Save Changes', 'myplugin' );  // missing hyphen

// Wrong - copy-pasted from another plugin
$wrong = __( 'Save Changes', 'other-plugin' );

// Wrong - WordPress core domain; works for core strings but not yours
$wrong = __( 'Save Changes', 'default' );

Encuentre las incoherencias buscando en su base de código:

grep -rE "__\(|_e\(|_n\(|_x\(" --include="*.php" .

Observe el último argumento de cada coincidencia. Todos deberían ser el dominio de texto de su plugin. Si encuentra erratas o errores de copiar y pegar, corríjalos y vuelva a ejecutar wp i18n make-pot para actualizar el .pot.

Para el código de JavaScript que usa @wordpress/i18n, se aplica la misma regla. wp_set_script_translations() en PHP también debe pasar el dominio coincidente:

wp_set_script_translations( 'my-plugin-editor', 'my-plugin', '...' );
//                                                ^^^^^^^^^^^
//                                                Must match the JS calls

Detecte los mismos problemas antes de la entrega con la revisión visual con IA

El bucle de diagnóstico anterior es reactivo. Falta una traducción y usted sale a la caza de la causa. La revisión visual con IA de PTC detecta los mismos problemas antes de la entrega. Inspecciona el plugin renderizado en cada idioma de destino tras cada actualización de traducción e informa de qué falta o qué está mal.

Para una cadena codificada a mano en inglés fuera de __() (Causa 1 anterior), la revisión visual con IA ve la cadena sin traducir en el plugin renderizado. PTC genera un prompt listo para pegar en Cursor o Claude Code para envolver la cadena en __(). Para una discrepancia de dominio de texto (la comprobación de la sección anterior), ve la cadena sin traducir cuando otras cadenas de la misma pantalla sí están traducidas, e informa de la incoherencia.

Si aún no ha activado la revisión visual con IA, consulte el tutorial de temas y plugins de WordPress para configurarla.

Cuando las tres comprobaciones pasan y aún faltan traducciones

Si ha comprobado las tres causas y las traducciones siguen sin aparecer, escriba un correo electrónico al soporte de PTC con:

  • El dominio de texto de su plugin.
  • Uno de los nombres de archivo .mo (p. ej., my-plugin-es_ES.mo).
  • Una captura de pantalla del panel de PTC que muestre la cadena afectada con su traducción.
  • La configuración de idioma del sitio en Settings > General.

La mayoría de los casos de "traducción que falta" se reducen a una de las causas anteriores. Los casos límite (versiones específicas de WordPress, resolución de configuración regional en MultiSite, conflicto con otro plugin de i18n) a veces requieren una segunda revisión.

Mantenga sincronizadas las futuras versiones con la localización continua

Una vez que sus traducciones se carguen correctamente, configure el flujo de trabajo de localización continua para que las futuras versiones se mantengan sincronizadas con sus traducciones - automáticamente, en cada push a main.