PTC

Le traduzioni del plugin WordPress non vengono visualizzate? Risolvi le traduzioni mancanti

Le traduzioni mancano dopo un'esecuzione di PTC? Quattro controlli permettono di individuare quasi ogni causa. Verifica che la stringa sia arrivata a PTC, che il nome del file .mo corrisponda a quello previsto da WordPress e che il text domain sia coerente in tutto il codice. Questa guida ti accompagna in ogni controllo nell'ordine in cui devono essere eseguiti.

Lo stesso ordine diagnostico funziona sia che tu abbia tradotto con PTC (Private Translation Cloud), GlotPress o qualsiasi altro strumento basato su gettext. Le modalità di errore sono inerenti alla pipeline i18n di WordPress, non a un particolare traduttore.

Conferma che la stringa sia arrivata a PTC

La prima domanda è se la stringa sia presente nel tuo progetto PTC. Se una stringa non è stata estratta nel tuo file .pot, PTC non l'ha mai vista. Il file .po non contiene alcuna traduzione per essa. Il plugin in esecuzione mostrerà il fallback nella lingua di origine.

Come controllare:

  1. Apri la stringa interessata nel plugin in esecuzione e copia il suo testo esatto.
  2. Vai nel tuo pannello di controllo PTC, apri la scheda Translations e cerca la stringa.
  3. Se non c'è, PTC non l'ha mai ricevuta.

Seguono tre cause comuni.

Causa 1: la stringa manca nel tuo file POT

wp i18n make-pot estrae solo le stringhe all'interno delle funzioni i18n riconosciute. Ciò significa __(), _e(), _n(), _x() e le varianti con escape, con il text domain corretto. Le stringhe all'interno di un domain errato vengono saltate. Le stringhe hardcoded al di fuori di una funzione i18n vengono saltate.

Esegui nuovamente l'estrazione e verifica che la stringa sia ora nel .pot:

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

Se grep restituisce la stringa con un msgid, l'estrazione funziona. Carica nuovamente il nuovo .pot su PTC e traduci di nuovo. Se grep non restituisce nulla, la stringa è hardcoded e non è racchiusa in __(). Questo è il tuo bug. Racchiudi la stringa e procedi a una nuova estrazione.

Causa 2: il testo non è racchiuso in una funzione gettext

Ogni stringa traducibile nel tuo codice ha bisogno di un wrapper. Usa __(), esc_html__(), _e(), _n() o _x() con il text domain corretto:

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

Causa 3: le stringhe JavaScript non sono state contrassegnate come traducibili

Se il tuo plugin include testo traducibile in JavaScript:

  1. Nel pannello di controllo PTC, vai su Settings > Monitored Files.
  2. Modifica il file di risorse pertinente e abilita “Is this a WordPress project with localizable JavaScript?”

Questo indica a PTC di scansionare i file JavaScript alla ricerca di stringhe traducibili. PTC rigenera le traduzioni e apre una nuova merge request con i file aggiornati.

Quindi assicurati che WordPress sappia dove caricare i file di traduzione .json prodotti da PTC. Chiama wp_set_script_translations() con il percorso corretto:

// 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'
);

Questo indica a WordPress di caricare i file .json dalla cartella del tuo plugin o tema.

Conferma che WordPress stia caricando il tuo file .mo

Se la stringa è in PTC e il file .mo esiste nella directory languages/ del tuo plugin ma il plugin renderizzato mostra ancora l'inglese, WordPress non riesce a caricare il file .mo.

Diagnostica 1: il locale del sito è impostato correttamente? Vai su Impostazioni > Generale > Lingua del sito in wp-admin e conferma che corrisponda alla tua lingua di destinazione. Ad esempio, impostalo su “Español” per testare lo spagnolo. Se il sito è in inglese, il tuo .mo spagnolo non verrà mai caricato. Questo non è un bug.

Diagnostica 2: load_plugin_textdomain() è effettivamente in esecuzione? Aggiungi una riga di debug temporanea:

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 ) );
} );

Ricarica una pagina e controlla il log degli errori PHP. loaded: true significa che WordPress ha trovato e caricato un file .mo per il locale corrente. loaded: false significa che non l'ha fatto. La causa è solitamente una mancata corrispondenza del nome del file (vedi la sezione successiva) o un percorso della directory errato.

Diagnostica 3: il timing dell'hook è corretto? load_plugin_textdomain() deve essere eseguito sull'hook init. Questo è l'hook canonico affinché le traduzioni vengano applicate alle stringhe stampate durante la normale elaborazione della richiesta.

Diagnostica 4: le traduzioni della community stanno sovrascrivendo i tuoi file inclusi? Per impostazione predefinita, WordPress dà la priorità ai file di traduzione memorizzati in /wp-content/languages/. Se il tuo plugin o tema ha traduzioni fornite dalla community su WordPress.org, quei file possono sovrascrivere i file .mo inclusi nel tuo progetto. Per evitare ciò, usa il filtro load_textdomain_mofile per forzare il caricamento del percorso del tuo file incluso prima che WordPress controlli la directory globale. I progetti con più text domain (un plugin che ne incorpora un altro) necessitano che ogni domain venga caricato separatamente. Ogni domain richiede la propria chiamata a load_plugin_textdomain() o load_theme_textdomain().

Assicurati che il nome del file MO corrisponda al pattern di ricerca di WordPress

La ricerca dei file .mo di WordPress segue una convenzione di denominazione rigorosa. Anche un solo carattere errato e WordPress torna silenziosamente all'inglese.

La convenzione dipende da dove posizioni il file:

Posizione Pattern Esempio
/languages/ del plugin {text-domain}-{locale}.mo my-plugin-de_DE.mo
/languages/ del tema {locale}.mo de_DE.mo
Dir globale (/wp-content/languages/...) {text-domain}-{locale}.mo my-theme-de_DE.mo

Alcuni esempi pratici:

  • my-plugin-es_ES.mo per lo spagnolo (Spagna)
  • my-plugin-fr_FR.mo per il francese (Francia)
  • my-plugin-pt_BR.mo per il portoghese (Brasile)
  • my-plugin-zh_CN.mo per il cinese semplificato
  • my-plugin-ja.mo per il giapponese (alcuni locale non hanno il suffisso regionale)

Errori comuni:

  • Prefisso text-domain errato. Se l'header Text Domain del tuo plugin è my-plugin ma il file .mo è nominato myplugin-es_ES.mo (senza trattino), WordPress non lo troverà. Il prefisso deve corrispondere esattamente al valore Text Domain.
  • Codice locale errato. es.mo invece di es_ES.mo. WordPress utilizza codici locale regionali. es_ES, es_MX e es_AR sono file diversi. Un codice lingua semplice funziona solo quando non esiste alcun file regionale.
  • Trattino vs underscore. I codici locale usano l'underscore (es_ES), mai il trattino (es-ES). Questo trae in inganno gli sviluppatori che copiano i codici locale dagli header Accept-Language del browser o da fonti BCP 47, dove il trattino è lo standard.
  • Directory errata. L'header Domain Path deve puntare alla directory che contiene i tuoi file .mo. Se Domain Path è /languages e i tuoi file .mo sono in /lang/, WordPress non li troverà.

Controlla elencando i file prodotti da PTC rispetto al locale utilizzato dal tuo sito:

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

Se i nomi sembrano corretti ma le traduzioni non vengono ancora caricate, esegui la diagnostica load_plugin_textdomain() sopra per confermare che WordPress stia trovando la directory.

Controlla che il tuo text domain sia coerente in tutto il codice

Questo è il killer silenzioso. Ogni chiamata a __(), _e(), _n(), _x() nel tuo codice passa un text domain come ultimo argomento. Se anche una sola chiamata passa il domain errato, quella singola stringa non verrà tradotta. Tutte le altre stringhe nel plugin funzioneranno correttamente.

// 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' );

Trova le incongruenze usando grep nel tuo codebase:

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

Osserva l'ultimo argomento di ogni corrispondenza. Dovrebbero essere tutti il text domain del tuo plugin. Se trovi refusi o errori di copia-incolla, correggili ed esegui nuovamente wp i18n make-pot per aggiornare il .pot.

Per il codice JavaScript che utilizza @wordpress/i18n, si applica la stessa regola. Anche wp_set_script_translations() in PHP deve passare il domain corrispondente:

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

Individua gli stessi problemi prima del rilascio con AI Visual QA

Il ciclo diagnostico sopra descritto è reattivo. Manca una traduzione e vai alla ricerca della causa. L'AI Visual QA di PTC individua gli stessi problemi prima che vengano rilasciati. Ispeziona il plugin renderizzato in ogni lingua di destinazione dopo ogni aggiornamento della traduzione e segnala cosa manca o cosa è errato.

Per una stringa inglese hardcoded al di fuori di __() (Causa 1 sopra), l'AI Visual QA vede la stringa non tradotta nel plugin renderizzato. PTC genera un prompt pronto da incollare per Cursor o Claude Code per racchiudere la stringa in __(). Per una mancata corrispondenza del text domain (il controllo della sezione precedente), vede la stringa non tradotta quando altre stringhe nella stessa schermata sono tradotte, e segnala l'incongruenza.

Se non hai ancora abilitato l'AI Visual QA, consulta il tutorial per temi e plugin WordPress per la configurazione.

Quando i quattro controlli hanno esito positivo e le traduzioni mancano ancora

Se hai eseguito tutti e quattro i controlli e le traduzioni non vengono ancora visualizzate, invia un'e-mail al supporto PTC con:

  • Il text domain del tuo plugin.
  • Uno dei nomi dei file .mo (es. my-plugin-es_ES.mo).
  • Uno screenshot del pannello di controllo PTC che mostra la stringa interessata con la sua traduzione.
  • L'impostazione della lingua del sito da Impostazioni > Generale.

La maggior parte dei casi di “traduzione mancante” si riconduce a una delle cause sopra indicate. I casi limite (versioni specifiche di WordPress, risoluzione del locale in MultiSite, conflitto con un altro plugin i18n) a volte richiedono un secondo controllo.

Mantieni i futuri rilasci sincronizzati con la traduzione continua

Una volta che le tue traduzioni vengono caricate correttamente, imposta il workflow di traduzione continua in modo che i futuri rilasci rimangano sincronizzati con le tue traduzioni — automaticamente, a ogni push su main.