Cache multilingue di WP Rocket: perché la cache delle versioni tradotte sparisce quando si salva una bozza, e la soluzione

La cache multilingue di WP Rocket è una cache delle pagine salvata separatamente in una cartella di lingua per ogni URL tradotto di TranslatePress. Su un server WordPress con Nginx + Apache abbiamo seguito nel codice di WP Rocket perché la cache delle pagine tradotte spariva con l'intera cartella della lingua ogni volta che si salvava una bozza, e l'abbiamo risolto con un codice che esclude gli articoli non pubblicati dalla pulizia della cache delle pagine tradotte e avvisa di nuovo il preload degli URL che cancelliamo noi.
Il tempo al primo byte, misurato nello stesso server, era di 0,015 secondi con la cache della pagina tradotta e di 2,492 secondi senza. Quando una cartella di lingua si svuota, i visitatori delle pagine tradotte ricevono questa risposta lenta finché qualcuno non riapre l'URL e la cache viene ricreata.
1️⃣ Come è organizzata la cache multilingue di WP Rocket: cartelle per lingua e pulizia delle pagine tradotte
Una pagina tradotta mostra l'articolo originale tradotto, quindi è facile pensare che la sua cache stia insieme all'originale, ma WP Rocket mette in cache gli URL tradotti come pagine separate. Sotto la cartella della cache compaiono cartelle di lingua come [en] e [ja] accanto alle cartelle degli articoli originali, e gli articoli tradotti vi sono salvati con i loro slug tradotti.
Quando modifichi un articolo, l'integrazione di WP Rocket con TranslatePress elimina anche la cache delle pagine tradotte di quell'articolo. Anche la documentazione ufficiale dice che una modifica normale pulisce tutte le versioni tradotte, mentre una modifica nell'editor di traduzione di TranslatePress pulisce solo la lingua cambiata.
// wp-rocket/inc/ThirdParty/Plugins/I18n/TranslatePress.php (3.23.5.1)
'post_updated' => 'clear_post_languages', // gira ogni volta che si salva un articolo
public function clear_post_languages( $post_id ) {
// …
$default_permalink = get_permalink( $post_id ); // lo stato dell'articolo non viene controllato
foreach ( $trp_settings['translation-languages'] as $language ) {
if ( $language === $trp_settings['default-language'] ) {
continue;
}
$clear_urls[] = $converter->get_url_for_language( $language, $default_permalink, '' );
}
// …
rocket_clean_files( $clear_urls );
}La funzione di integrazione converte l'URL dell'articolo nell'URL tradotto per ogni lingua e poi li passa alla funzione di pulizia della cache [rocket_clean_files]. In questo processo nulla controlla lo stato dell'articolo, quindi gli URL tradotti vengono creati ed eliminati allo stesso modo, che l'articolo sia pubblicato o una bozza.
2️⃣ Salvare una bozza: viene eliminata l'intera cartella della lingua
Salvare una bozza non è estraneo alla cache delle pagine tradotte. Prima della pubblicazione il permalink di un articolo non è uno slug ma la forma [?p=ID articolo], e TranslatePress converte quell'URL in uno con il percorso della lingua, come [/en/?p=ID articolo].
[rocket_clean_files] toglie la query dall'URL e trova la posizione della cache solo dal percorso. Se il percorso rimasto è [/en/], significa l'intera cartella di cache di quella lingua, e se il bersaglio è una cartella viene eliminata ricorsivamente, sottocartelle comprese.
// wp-rocket/inc/functions/files.php (3.23.5.1) — dentro rocket_clean_files()
$parsed_url = get_rocket_parse_url( $url ); // divide percorso e query
// …
$entry = $dir . $parsed_url['path']; // …/example.com/en/
// …
if ( $filesystem->is_dir( $entry ) ) {
rocket_rrmdir( $entry, [], $filesystem ); // elimina l'intera cartella ricorsivamente
} else {
$filesystem->delete( $entry );
}La home passa per lo stesso percorso. Il suo URL [/] viene convertito in [/en/], quindi anche salvare la home pubblicata elimina l'intera cartella della lingua. Basta modificare il titolo di una bozza e salvarla di nuovo per svuotare le cartelle di cache di tutte e quattro le lingue, e dagli orari di salvataggio e dai log di eliminazione della cache abbiamo confermato la stessa eliminazione ripetuta più di 30 volte in una notte con molti salvataggi di bozze.
Nel codice anche il salvataggio automatico dell'editor segue lo stesso percorso. Le revisioni salvate mentre modifichi un articolo pubblicato usano anch'esse un URL della forma [?p=].
Su un sito di test con Nginx + Apache abbiamo modificato un articolo pubblicato nell'editor contando i file nelle cartelle di lingua. Dopo il primo salvataggio automatico le cartelle inglese e giapponese avevano ancora 20 file ciascuna, e dopo il secondo, un minuto più tardi, erano entrambe a 0.
Il primo salvataggio automatico crea una nuova revisione, e dal secondo in poi la stessa revisione viene aggiornata e salvata, quindi scatta [post_updated]. Se continui a modificare dopo il primo, la cache delle pagine tradotte viene eliminata con la cartella della lingua anche senza premere il pulsante di salvataggio.
Lo stesso sintomo è aperto nel repository ufficiale di WP Rocket come issue #6130 dal 31 agosto 2023. La pull request #7616 per correggerlo è stata inviata a settembre 2025 ma non è stata unita, e anche il changelog della 3.23.5.1, uscita il 2 ottobre 2026, non contiene correzioni.
3️⃣ La soluzione: pulire la cache delle pagine tradotte solo per gli articoli pubblicati
Finché non arriva una correzione ufficiale, stacchi la funzione di integrazione e la sostituisci con una che pulisce le pagine tradotte solo quando l'URL è certo. Il workaround pubblicato nei commenti dell'issue va nella stessa direzione, uscendo subito dalla funzione di integrazione se l'articolo non è pubblicato.
Una condizione che controlla solo lo stato dell'articolo lascia però due casi. La home pulisce l'intera cartella della lingua quando viene salvata, anche se è pubblicata, e quando riporti un articolo pubblicato a bozza la cache delle pagine tradotte non viene eliminata, quindi l'articolo ritirato continua ad aprirsi agli URL tradotti.
<?php
/**
* Plugin Name: Rocket TranslatePress Draft Fix
* Description: Limita l'eliminazione della cache delle pagine tradotte dell'integrazione WP Rocket–TranslatePress ai casi in cui l'URL è certo
*/
// 1. Stacca la funzione di integrazione di WP Rocket da post_updated e conservala
add_action( 'init', function () {
global $wp_filter;
if ( empty( $wp_filter['post_updated'] ) ) {
return;
}
foreach ( $wp_filter['post_updated']->callbacks as $priority => $callbacks ) {
foreach ( $callbacks as $cb ) {
$fn = $cb['function'];
if ( is_array( $fn ) && is_object( $fn[0] )
&& 0 === strpos( get_class( $fn[0] ), 'WP_Rocket\\' )
&& false !== stripos( get_class( $fn[0] ), 'TranslatePress' ) ) {
remove_action( 'post_updated', $fn, $priority );
$GLOBALS['rtdf_original'] = $fn;
}
}
}
}, 9999 );
// 2. Funzione sostitutiva
add_action( 'post_updated', function ( $post_id, $after, $before ) {
if ( empty( $GLOBALS['rtdf_original'] ) || ! class_exists( 'TRP_Translate_Press' ) ) {
return;
}
$trp = TRP_Translate_Press::get_trp_instance();
$converter = $trp->get_component( 'url_converter' );
$settings = $trp->get_component( 'settings' )->get_settings();
$languages = array_diff( $settings['translation-languages'], [ $settings['default-language'] ] );
// Home — solo i file di cache della home della lingua, non la cartella
if ( 'page' === get_option( 'show_on_front' ) && (int) get_option( 'page_on_front' ) === (int) $post_id ) {
$urls = [];
add_filter( 'trp_add_language_to_home_url_check_for_admin', '__return_false' );
foreach ( $languages as $lang ) {
$home = $converter->get_url_for_language( $lang, home_url( '/' ), '' );
$dir = WP_ROCKET_CACHE_PATH . wp_parse_url( $home, PHP_URL_HOST ) . wp_parse_url( $home, PHP_URL_PATH );
array_map( 'unlink', glob( $dir . 'index*.html*' ) ?: [] );
$urls[] = $home;
}
remove_filter( 'trp_add_language_to_home_url_check_for_admin', '__return_false' );
do_action( 'rocket_after_clean_terms', $urls ); // avvisa il preload (5️⃣)
return;
}
// Salvataggio di un articolo pubblicato — la funzione originale di WP Rocket così com'è
if ( 'publish' === $after->post_status ) {
call_user_func( $GLOBALS['rtdf_original'], $post_id );
return;
}
// Pubblicato → bozza·privato·cestino — solo le pagine tradotte dell'URL di prima del ritiro
if ( 'publish' === $before->post_status ) {
$old = get_permalink( $before );
$urls = [];
add_filter( 'trp_add_language_to_home_url_check_for_admin', '__return_false' );
foreach ( $languages as $lang ) {
$urls[] = $converter->get_url_for_language( $lang, $old, '' );
}
remove_filter( 'trp_add_language_to_home_url_check_for_admin', '__return_false' );
rocket_clean_files( $urls );
}
// Tutto il resto (bozze·revisioni·salvataggio automatico) non ha URL tradotto, quindi non si elimina nulla
}, 10, 3 );La prima parte trova la funzione di integrazione registrata da WP Rocket, la stacca da [post_updated] e conserva la funzione originale. La funzione sostitutiva pulisce solo i file di cache della home della lingua per la home, esegue così com'è la funzione originale conservata per gli articoli pubblicati e, quando un articolo pubblicato viene ritirato, trova ed elimina le pagine tradotte usando l'URL di prima.
Salvato come file PHP nella cartella [wp-content/mu-plugins/], ha effetto subito senza attivazione, e cancellando il file WP Rocket torna al comportamento originale. In un test con codice che si comporta allo stesso modo, risalvare una bozza ha lasciato invariato il numero di file nelle cartelle di lingua, e risalvare un articolo pubblicato ha pulito solo le cartelle dell'originale e delle pagine tradotte di quell'articolo.
Prima e dopo aver aggiunto il codice sopra, abbiamo confrontato il numero di file nelle cartelle di lingua per quattro casi nello stesso ambiente. Le cartelle inglese e giapponese contenevano ciascuna 20 file di cache per PC e mobile della home della lingua e di quattro articoli.
Prima del codice, salvare una bozza, salvare la home e ritirare la pubblicazione portavano entrambe le cartelle a 0, e solo il salvataggio di un articolo pubblicato eliminava soltanto la cache delle pagine tradotte di quell'articolo.
Dopo il codice, salvando una bozza e con il salvataggio automatico dell'editor sono rimasti tutti e 20 i file. Salvare la home ha eliminato i 4 file di cache della home della lingua, e salvare o ritirare un articolo pubblicato ha eliminato solo le 4 pagine tradotte di quell'articolo, lasciandone 16; l'URL tradotto in inglese dell'articolo ritirato ha risposto 404.
| Caso | Prima della correzione | Dopo aver aggiunto il codice | Cache eliminata dopo la correzione |
|---|---|---|---|
| Salvare una bozza | 20 → 0 | 20 → 20 | Nessuno |
| Salvare un articolo pubblicato | Eliminate solo le pagine tradotte di quell'articolo | 20 → 16 | 4 pagine tradotte di quell'articolo |
| Salvare la home | 20 → 0 | 20 → 16 | 4 file di cache della home della lingua |
| Ritirare la pubblicazione | 20 → 0 | 20 → 16 | 4 pagine tradotte di quell'articolo · l'URL tradotto risponde 404 |
4️⃣ Ricostruzione del preload mancata: stato completato rimasto in coda
Anche bloccando i salvataggi delle bozze, il preload non riempie di nuovo i file di cache eliminati senza il segnale di eliminazione di una funzione di WP Rocket. Il preload di WP Rocket usa una tabella di coda che registra uno stato per ogni URL: gli URL da richiedere sono in attesa, quelli richiesti in corso, quelli in cache diventano completati e quelli non finiti entro 3 minuti diventano falliti.
Un URL completato torna in attesa in tre casi: quando il suo file è stato rimosso a fine durata della cache, quando WP Rocket ha inviato un segnale di eliminazione pulendolo, o quando è fallito più di 12 ore prima. Se passi false come terzo argomento di [rocket_clean_files] o elimini i file direttamente, il segnale non parte, quindi spariscono solo i file di cache mentre la coda li mostra ancora come completati.
Il codice che riceve il segnale di eliminazione e poi pulisce altre cache passa false come terzo argomento per evitare chiamate ripetute. Quando abbiamo controllato le cache delle pagine tradotte, 3 delle 65 pagine inglesi e 7 delle 65 giapponesi risultavano ancora completate in coda senza i file di cache.
Anche un collaboratore dell'assistenza di WP Rocket ha riconosciuto nei commenti dell'issue #6130 che dopo la pulizia della cache gli URL nella tabella restano completati e lo stato va fuori sincrono. Una proposta di allineare periodicamente la tabella ai file di cache (#2939) è stata chiusa nel 2020 senza essere realizzata.
5️⃣ Registrare di nuovo nel preload: segnalare alla coda gli URL cancellati da te
Per gli URL che elimini tu, basta una riga che avvisa il preload subito dopo l'eliminazione. Quando il preload riceve il segnale [rocket_after_clean_terms], rimette in attesa gli URL ricevuti e aggiunge quelli che mancano nella tabella.
// Dopo aver eliminato senza segnale — registra di nuovo l'array degli URL eliminati nella coda del preload
rocket_clean_files( $urls, null, false ); // terzo argomento false = nessun segnale di eliminazione
do_action( 'rocket_after_clean_terms', $urls ); // il preload rimette questi URL in attesa (pending)All'interno di WP Rocket ricevono questo segnale solo la funzione di coda del preload e l'integrazione di hosting SpinUpWP, e la funzione del preload aggiorna solo le righe della coda senza eliminare file di cache di WP Rocket né rinviare il segnale, quindi non nascono chiamate ripetute. I siti che puliscono la cache solo con le funzioni di WP Rocket e lasciano il terzo argomento al valore predefinito inviano già il segnale e non hanno bisogno di questa riga.
Dopo aver aggiunto questa riga abbiamo pulito la cache di un articolo con pagine tradotte in quattro lingue, e in 2 secondi le quattro righe della coda sono passate a in attesa. In due test su un server che esegue il cron ogni minuto, tutti gli 8 file di cache PC e mobile delle pagine tradotte sono stati ricreati dopo 101 e 153 secondi. Lo controlli dallo stato nella tabella della coda e dai file nella cartella della cache.
# Stato di quell'URL nella tabella della coda (il wp_ prima del nome della tabella è il prefisso del sito)
wp db query <<'SQL'
SELECT url, status, modified FROM wp_wpr_rocket_cache WHERE url LIKE '%/en/sample-post-en'
SQLurl status modified
https://example.com/en/sample-post-en pending 2026-10-17 09:10:48# Se i file di cache sono tornati dopo circa un minuto
ls -l wp-content/cache/wp-rocket/example.com/en/sample-post-en/total 240
-rw-r--r-- 1 example nobody 95084 Oct 17 18:12 index-https.html
-rw-r--r-- 1 example nobody 22352 Oct 17 18:12 index-https.html_gzip
-rw-r--r-- 1 example nobody 95083 Oct 17 18:12 index-mobile-https.html
-rw-r--r-- 1 example nobody 22348 Oct 17 18:12 index-mobile-https.html_gzipSubito dopo l'eliminazione lo stato diventa [pending], e quando il preload invia la richiesta e il file di cache viene creato diventa [completed]. Se lo stato è [completed] ma non c'è il file di cache, quell'URL è stato eliminato senza il segnale.
Quando abbiamo salvato la home e il codice sopra ha eliminato i file di cache della home della lingua inviando il segnale, gli URL della home inglese e giapponese sono tornati in coda. Le cache PC e mobile delle home delle lingue sono state ricreate al più tardi alla seconda esecuzione del cron.
In due test sono serviti 47 e 91 secondi dal salvataggio all'ultimo file di cache.
🔢 FAQ & contenuti consigliati














ℹ️ Informativa sull'affiliazione
I contenuti di questo sito includono link di affiliazione. Se un visitatore acquista un prodotto o un servizio tramite uno di questi link, il sito riceve una commissione dal venditore. In questo processo l'importo pagato dall'acquirente (durante le promozioni l'importo scende↓) non aumenta. Prezzi, sconti e disponibilità indicati si riferiscono al momento della stesura e possono differire da quelli reali: prima di acquistare verifica sempre presso il venditore. I prodotti vengono scelti e valutati secondo criteri propri, e le commissioni non influiscono sull'ordine di presentazione né sul contenuto delle valutazioni.

