Gestire un sito WordPress multilingua significa spesso trovarsi davanti a piccoli problemi che, all’apparenza, sembrano facilmente risolvibili dal pannello di amministrazione. Quando però il numero di contenuti cresce, intervenire manualmente non è più una soluzione sostenibile.
Mi sono trovata proprio in questa situazione con un Custom Post Type WordPress gestito tramite Polylang.
Il Custom Post Type, chiamato prodotti, era disponibile in italiano e inglese. Il problema era molto preciso: le date di pubblicazione dei prodotti italiani e delle relative traduzioni inglesi non coincidevano.
Nel mio caso la lingua italiana doveva essere considerata il contenuto master. Di conseguenza, avevo bisogno che la data della versione inglese fosse sempre uguale a quella impostata nella corrispondente versione italiana.
Vediamo come ho affrontato il problema e quale soluzione ho adottato.
Di cosa parlerò in questa pagina
Il problema: date diverse tra traduzioni Polylang
La struttura del sito era questa:
- WordPress;
- Custom Post Type
prodotti; - Polylang per la gestione del multilingua;
- italiano come lingua principale;
- inglese come traduzione.
Nel corso del tempo alcuni prodotti erano stati creati o tradotti in momenti diversi. WordPress aveva quindi assegnato date differenti ai due post.
Potevo avere, per esempio:
Prodotto IT
Data pubblicazione: 15/03/2024
Prodotto EN
Data pubblicazione: 22/07/2025
Dal punto di vista editoriale, però, si trattava dello stesso prodotto, semplicemente disponibile in due lingue.
Avevo quindi bisogno di ottenere:
Prodotto IT
15/03/2024
↓ sincronizzazione
Prodotto EN
15/03/2024
Con una regola fondamentale: è sempre l’italiano a comandare.
Primo tentativo: modificare manualmente le date
La soluzione più immediata sarebbe stata aprire ogni prodotto inglese e modificare manualmente la data di pubblicazione.
Tecnicamente funziona.
Praticamente, però, non è una vera soluzione.
Con pochi contenuti può essere accettabile, ma con decine o centinaia di prodotti significa:
- aprire il prodotto italiano;
- controllarne la data;
- aprire la traduzione inglese;
- modificare la data;
- salvare;
- ripetere tutto per ogni prodotto.
Inoltre rimane un problema ancora più importante: le date potrebbero tornare a essere disallineate in futuro.
Ho quindi scartato la soluzione manuale.
Secondo tentativo: sincronizzazione massiva una tantum
Il secondo approccio è stato molto più interessante: utilizzare direttamente le funzioni messe a disposizione da Polylang per recuperare la traduzione associata a un determinato post.
Polylang permette infatti di ottenere l’ID della traduzione tramite:
pll_get_post($post_id, 'en');
Questo rende possibile recuperare tutti i prodotti italiani, trovare la corrispondente versione inglese e aggiornare la data.
Una prima soluzione può quindi essere questa:
add_action('init', function () {
if (!current_user_can('administrator')) {
return;
}
if (!isset($_GET['sync_dates'])) {
return;
}
$args = [
'post_type' => 'prodotti',
'posts_per_page' => -1,
'lang' => 'it',
'post_status' => 'any'
];
$posts = get_posts($args);
foreach ($posts as $post_it) {
$post_en_id = pll_get_post($post_it->ID, 'en');
if (!$post_en_id) {
continue;
}
wp_update_post([
'ID' => $post_en_id,
'post_date' => $post_it->post_date,
'post_date_gmt' => $post_it->post_date_gmt
]);
}
echo 'Allineamento completato';
exit;
});
A questo punto è sufficiente richiamare, mentre si è autenticati come amministratori:
https://www.example.com/?sync_dates=1
Lo script:
- recupera i prodotti italiani;
- cerca per ognuno la traduzione inglese;
- ignora quelli che non hanno una traduzione;
- copia
post_date; - copia anche
post_date_gmt; - aggiorna il post inglese.
Perché questa soluzione non era sufficiente
Il problema non era tanto nel funzionamento dello script: la sincronizzazione massiva risolveva correttamente lo storico.
Non risolveva però il problema alla radice.
Se successivamente qualcuno modificava la data del prodotto italiano, la traduzione inglese rimaneva con la vecchia data.
Avrei quindi dovuto ricordarmi periodicamente di rilanciare la sincronizzazione.
Era meglio dell’intervento manuale, ma stavo automatizzando la correzione del problema, non la sua prevenzione.
La soluzione definitiva: sincronizzare automaticamente la data al salvataggio
La soluzione che ho scelto è stata quindi diversa: agganciare la sincronizzazione al salvataggio del Custom Post Type.
WordPress mette a disposizione un hook specifico:
save_post_{post_type}
Nel mio caso:
save_post_prodotti
Quando viene salvato un prodotto posso quindi verificare se appartiene alla lingua italiana e, in quel caso, aggiornare automaticamente la traduzione inglese.
Il codice diventa:
add_action('save_post_prodotti', function ($post_id) {
if (wp_is_post_revision($post_id)) {
return;
}
if (!function_exists('pll_get_post_language')) {
return;
}
if (pll_get_post_language($post_id) !== 'it') {
return;
}
$post_en_id = pll_get_post($post_id, 'en');
if (!$post_en_id) {
return;
}
$post_it = get_post($post_id);
if (!$post_it) {
return;
}
wp_update_post([
'ID' => $post_en_id,
'post_date' => $post_it->post_date,
'post_date_gmt' => $post_it->post_date_gmt
]);
});
Come funziona la sincronizzazione
La logica è volutamente semplice.
Quando WordPress salva un elemento del Custom Post Type prodotti, il codice controlla innanzitutto che non si tratti di una revisione:
if (wp_is_post_revision($post_id)) {
return;
}
Successivamente verifica che Polylang sia disponibile e controlla la lingua del post:
if (pll_get_post_language($post_id) !== 'it') {
return;
}
Questo passaggio è fondamentale perché stabilisce la gerarchia:
Italiano → Inglese
e mai:
Inglese → Italiano
La versione italiana rimane quindi il master.
A questo punto recupero l’ID della traduzione inglese:
$post_en_id = pll_get_post($post_id, 'en');
Se la traduzione non esiste, non succede nulla.
Se invece esiste, recupero il post italiano e trasferisco:
'post_date'
'post_date_gmt'
alla versione inglese.
Da questo momento, ogni volta che viene modificata la data del prodotto italiano, la relativa versione inglese viene automaticamente riallineata.
Attenzione a post_date e post_date_gmt
Un dettaglio importante è non limitarsi ad aggiornare soltanto:
post_date
WordPress conserva infatti anche:
post_date_gmt
Per mantenere coerenti i dati è quindi preferibile trasferire entrambe le informazioni:
wp_update_post([
'ID' => $post_en_id,
'post_date' => $post_it->post_date,
'post_date_gmt' => $post_it->post_date_gmt
]);
In questo modo WordPress mantiene correttamente sia la data locale sia quella memorizzata in GMT.
Sincronizzazione iniziale + sincronizzazione futura
Alla fine, nel mio caso, la strategia migliore non è stata scegliere tra i due script, ma usarli per due scopi differenti.
Lo script massivo è utile una prima volta per correggere tutti i prodotti già presenti nel database.
L’hook:
save_post_prodotti
serve invece a impedire che il problema si ripresenti in futuro.
Il flusso diventa quindi:
PRODOTTI ESISTENTI
↓
sincronizzazione massiva una tantum
↓
date IT/EN allineate
NUOVI AGGIORNAMENTI
↓
salvataggio prodotto italiano
↓
save_post_prodotti
↓
ricerca traduzione Polylang
↓
aggiornamento automatico data EN
È una soluzione molto più robusta rispetto a una correzione periodica manuale.
E se il sito avesse più di due lingue?
La stessa logica può essere facilmente estesa.
Per esempio, se l’italiano deve essere master per inglese, francese e tedesco, possiamo definire le lingue da sincronizzare:
$languages = ['en', 'fr', 'de'];
foreach ($languages as $lang) {
$translation_id = pll_get_post($post_id, $lang);
if (!$translation_id) {
continue;
}
wp_update_post([
'ID' => $translation_id,
'post_date' => $post_it->post_date,
'post_date_gmt' => $post_it->post_date_gmt
]);
}
In questo modo la versione italiana rimane la sorgente principale e tutte le traduzioni ricevono la stessa data.
Perché preferisco questa soluzione
Il problema iniziale sembrava banale: avevo semplicemente delle date diverse tra italiano e inglese.
In realtà la domanda giusta non era:
Come posso correggere le date?
ma:
Come posso fare in modo che le date rimangano corrette anche in futuro?
È una distinzione che, nello sviluppo WordPress, fa spesso la differenza.
Una sincronizzazione massiva risolve lo stato attuale del database. Un hook sul salvataggio, invece, trasforma una regola editoriale in una regola applicativa.
Nel mio caso la regola era:
La data del prodotto italiano è quella ufficiale e tutte le sue traduzioni devono utilizzare la stessa data.
Una volta tradotta questa regola in codice, non devo più ricordarmi di applicarla manualmente.
Conclusione
Se utilizzi WordPress, Polylang e Custom Post Type e hai bisogno di mantenere sincronizzate le date di pubblicazione delle traduzioni, è possibile automatizzare completamente il processo.
Nel mio caso sono partita da una gestione manuale, sono passata a uno script di sincronizzazione massiva e sono infine arrivata alla soluzione che ritengo più corretta: utilizzare il contenuto italiano come master e sincronizzare automaticamente la data delle traduzioni tramite save_post e le API di Polylang.
La combinazione ideale è quindi:
- sincronizzazione una tantum per sistemare i contenuti esistenti;
- sincronizzazione automatica per mantenere allineati quelli futuri.
È un piccolo automatismo, ma elimina un’attività ripetitiva e soprattutto evita che il database torni lentamente in uno stato incoerente.
Domande frequenti
Sì. È possibile utilizzare le funzioni di Polylang per recuperare l’ID della traduzione e wp_update_post() per aggiornare automaticamente la relativa data di pubblicazione.
È possibile utilizzare:
pll_get_post($post_id, ‘en’);
dove en rappresenta lo slug della lingua della traduzione da recuperare.
Per questa specifica esigenza è possibile implementare programmaticamente una logica master. Nel mio caso controllo che il post salvato sia italiano prima di effettuare qualsiasi sincronizzazione, in modo che le modifiche alla versione inglese non possano cambiare la data italiana.
Sì, purché il Custom Post Type sia gestito da Polylang e disponga delle relative traduzioni. È inoltre possibile utilizzare l’hook specifico save_post_{post_type}, come save_post_prodotti.
Sì. Lo stesso principio può essere utilizzato per sincronizzare metadati e altri valori condivisi. Bisogna però valutare attentamente quali informazioni debbano essere comuni e quali, invece, debbano rimanere specifiche della singola lingua.