Traducere JSON WordPress: Traducerea JavaScript-ului Editorului de Blocuri

Ai tradus pluginul. Șirurile de caractere PHP apar perfect în setările de administrare, în șabloanele frontend, în notificările prin e-mail – toate localizate. Apoi deschizi editorul de blocuri, și fiecare etichetă din blocul tău personalizat Gutenberg este încăpățânat, batjocoritor în engleză. Butonul „Add Item”, titlurile panoului inspectorului, textul substituent. Fișierul tău .mo este încărcat. Deci, de ce nu se traduc aceste șiruri de caractere?
Deoarece, începând cu WordPress 5.0 și sosirea Gutenberg, șirurile de caractere JavaScript nu provin deloc din fișierul tău .mo. Ele necesită un fișier de traducere JSON WordPress complet separat, per-script – iar dacă nu îl generezi, editorul tău de blocuri rămâne în engleză, indiferent cât de complet este fișierul tău .po. Aceasta este una dintre cele mai comune și confuze lacune de localizare în dezvoltarea modernă de WordPress. Acest ghid explică exact de ce se întâmplă, cum funcționează sistemul de traducere JSON, numele de fișiere cu hash MD5 care încurcă pe toată lumea și setul complet de instrumente pentru a remedia problema.
De ce șirurile tale din editorul de blocuri rămân în engleză
Răspuns scurt: PHP și JavaScript utilizează două sisteme complet diferite de livrare a traducerilor în WordPress, iar fișierul tău .mo alimentează doar sistemul PHP.
Două sisteme de traducere, un singur plugin
Atunci când WordPress rulează load_plugin_textdomain(), citește fișierul tău .mo compilat în memoria PHP. Fiecare apel __(), _e() și _x() din codul tău PHP caută traducerea acolo. Acest lucru funcționează deoarece PHP randează pe partea de server – datele .mo sunt chiar acolo, în același proces.
JavaScript este diferit. Codul tău de bloc rulează în browser, mult după ce PHP și-a încheiat execuția. Nu poate accesa un fișier .mo de pe partea de server. În schimb, pachetul @wordpress/i18n – echivalentul JS al Gettext, expunând __(), _x() și sprintf() scripturilor tale – se așteaptă ca traducerile să fie livrate ca un pachet JSON atașat scriptului specific care le necesită.
Ce se întâmplă cu un șir de caractere JS netradus
Așadar, un bloc cu șiruri de caractere ca acestea:
import { __ } from '@wordpress/i18n';
registerBlockType( 'myplugin/feature-box', {
title: __( 'Feature Box', 'myplugin' ),
edit: () => {
return <Button>{ __( 'Add Item', 'myplugin' ) }</Button>;
},
} );
nu va găsi niciodată „Feature Box” sau „Add Item” în fișierul tău .mo, deoarece browserul nu citește niciodată fișiere .mo. Aceste șiruri de caractere trebuie să ajungă ca JSON, conectate la acest script handle exact. Dacă nu ai configurat acest lucru, apelurile JS __() pur și simplu returnează engleza originală – în tăcere, fără nicio eroare în consolă.
Conectarea traducerilor JSON cu wp_set_script_translations()
Puntea dintre scriptul tău și traducerile sale JSON este o singură funcție PHP: wp_set_script_translations(). Răspunsul la „cum știe WordPress ce fișier JSON aparține cărui script” este: tu îi spui, înregistrând scriptul și apoi declarând domeniul său de text și folderul în care se află JSON-ul.
Înregistrarea scriptului și a folderului său de traducere
add_action( 'init', function () {
wp_register_script(
'myplugin-editor',
plugins_url( 'build/index.js', __FILE__ ),
array( 'wp-blocks', 'wp-i18n', 'wp-element' ),
'1.0.0'
);
// Tell WordPress where this script's JSON translations live
wp_set_script_translations(
'myplugin-editor', // the registered script handle
'myplugin', // text domain
plugin_dir_path( __FILE__ ) . 'languages'
);
} );
Atunci când editorul încarcă myplugin-editor, WordPress știe acum să caute în folderul tău languages/ un fișier JSON care să corespundă acestui script și setării regionale a utilizatorului curent. Dacă găsește unul, injectează traducerile înainte ca scriptul tău să ruleze, iar apelurile JS __() se rezolvă corect. Handle-ul pe care îl transmiți trebuie să se potrivească exact cu un script înregistrat – un handle necorespunzător sau lipsă este a doua cea mai comună cauză a eșecului silențios al traducerilor.
Numele de fișier cu hash MD5 la care nimeni nu se așteaptă
Iată detaliul care deraiază aproape pe toată lumea. Fișierul JSON pe care WordPress îl caută nu este numit ceva ordonat precum myplugin-fr_FR.json. Este denumit cu un hash MD5 al căii sursă a scriptului:
Decodificarea modelului de nume de fișier
myplugin-fr_FR-a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6.json
Modelul este {textdomain}-{locale}-{md5}.json, unde hash-ul este MD5-ul căii relative către fișierul script (de exemplu build/index.js) așa cum este înregistrat. WordPress calculează acest hash la rulare pentru a găsi JSON-ul potrivit pentru scriptul potrivit. Dacă denumești manual fișierul, WordPress nu îl va găsi, și vei jura că sistemul este stricat când de fapt doar caută un alt nume de fișier.
Nu calculezi tu hash-ul. Comanda WP-CLI i18n o face pentru tine, motiv pentru care trebuie să utilizezi instrumentele în loc să creezi aceste fișiere manual. Înțelegerea faptului că hash-ul există, totuși, este ceea ce te scutește de ore întregi atunci când un fișier JSON este prezent în languages/ dar este totuși ignorat – este aproape întotdeauna o nepotrivire a hash-ului numelui de fișier, deoarece calea scriptului s-a schimbat.
Fluxul de lucru complet: de la make-pot la make-json
Vestea bună este că îți păstrezi traducerile în aceleași fișiere .po pe care le utilizezi deja. JSON-ul este un artefact derivat, generat la final. Răspunsul la întrebarea „trebuie să gestionez șirurile JS separat” este nu – ele se află în aceleași fișiere .pot/.po ca și șirurile tale PHP, iar o comandă suplimentară le separă pe cele JS în JSON.
Lanțul de patru comenzi
Iată pipeline-ul complet:
# 1. Extract ALL translatable strings (PHP and JS) into one template
wp i18n make-pot . languages/myplugin.pot
# 2. Translate languages/myplugin-fr_FR.po as usual (Poedit, AI, etc.)
# 3. Compile the .mo for PHP strings (server-side, as always)
wp i18n make-mo languages/
# 4. Generate the MD5-hashed JSON files for JS strings
wp i18n make-json languages/ --no-purge
Comanda make-pot de la Pasul 1 este suficient de inteligentă pentru a scana atât fișierele tale .php, cât și sursa .js/.jsx, astfel încât un singur .po per localitate conține totul. make-json de la Pasul 4 citește fiecare .po tradus, găsește intrările care proveneau din fișierele JavaScript și scrie un JSON cu hash corect pentru fiecare script. Flag-ul --no-purge păstrează și șirurile JS în fișierul tău .po, astfel încât un make-mo ulterior să nu le piardă – fără acesta, make-json elimină intrările JS din .po, ceea ce surprinde persoanele care rulează comenzile în ordinea greșită.
Un fișier JSON generat arată ca un set de traduceri în format Jed:
{
"translation-revision-date": "2026-06-12 10:00+0000",
"generator": "WP-CLI/2.x",
"domain": "messages",
"locale_data": {
"messages": {
"": { "domain": "messages", "lang": "fr_FR" },
"Feature Box": [ "Bloc fonctionnalité" ],
"Add Item": [ "Ajouter un élément" ]
}
}
}
WordPress citește locale_data și îl furnizează către @wordpress/i18n înainte ca scriptul tău să ruleze. Acum __( 'Add Item', 'myplugin' ) în browser returnează Ajouter un élément, iar editorul tău de blocuri este în sfârșit localizat.
Cum diferă acest lucru de i18next JSON
Ambele sisteme utilizează JSON, ambele vizează JavaScript, iar această similitudine superficială provoacă o confuzie reală. Nu sunt interschimbabile. JSON-ul editorului de blocuri WordPress este un pachet derivat din Gettext, cu hash MD5, per-script, consumat de @wordpress/i18n. JSON-ul i18next este un fișier cheie-valoare plat sau imbricat, consumat de react-i18next sau next-intl, cu propria sa sintaxă de {{interpolation}} și convenții pentru cheile de plural.
Dacă lucrezi în React sau Next.js pur, în afara WordPress, vrei abordarea i18next, pe care o acoperim în traducerea JSON i18next în React și Next.js. În interiorul WordPress, vrei fluxul de lucru make-json de mai sus. Amestecarea lor – de exemplu, scrierea manuală a unui JSON de stil i18next plat și așteptarea ca wp_set_script_translations() să-l încarce – pur și simplu nu va funcționa, deoarece WordPress caută formatul Jed cu hash, nu perechi arbitrare cheie-valoare.
O singură sursă, fiecare format de care ai nevoie
Fragilitatea în toate acestea este pasul de traducere din mijloc. Fișierul tău .po alimentează atât .mo (PHP), cât și JSON (JavaScript), deci o singură traducere greșită – un %s deformat, un tag <strong> rupt, o formă de plural redenumită – contaminează ambele ieșiri simultan. Și deoarece șirurile JS sunt încărcate asincron în browser, o eroare structurală acolo se manifestă adesea ca o etichetă goală sau un crash brusc, mai degrabă decât o revenire grațioasă.
O singură încărcare, PHP și JavaScript acoperite
Aici își găsește locul un pipeline de traducere care înțelege structura Gettext. SimplePoTranslate preia un fișier sursă .po sau .pot și produce o ieșire curată, tradusă în mai multe formate dintr-o singură încărcare – .po, .mo, .json, .php și .xliff – astfel încât nu ești nevoit să pui cap la cap instrumente separate pentru straturile tale PHP și JavaScript. Funcția sa Syntax Locking menține la locul lor %s, %1$s, {count} și HTML-ul inline, ceea ce contează dublu pentru șirurile editorului de blocuri, unde un placeholder stricat poate bloca întregul panou al editorului. Aprofundăm modelul o singură sursă, multe ieșiri în un fișier de intrare, cinci formate de ieșire.
Tu încă rulezi make-json pentru a produce fișierele hashed pe care le așteaptă WordPress – acest pas este specific WordPress și rămâne în build-ul tău. Dar traducerea în sine, partea care cel mai probabil va strica șirurile tale JS, este gestionată de un motor conștient de context în loc de un script de căutare și înlocuire.
Concluzie
Motivul pentru care editorul tău de blocuri rămâne în engleză este structural, nu o eroare: traducerea JSON WordPress este un sistem de livrare separat de fișierul .mo, construit special deoarece browserele nu pot citi datele Gettext de pe server. Odată ce înțelegi că șirurile JavaScript necesită JSON-uri cu hash MD5, generate per-script de wp i18n make-json și conectate cu wp_set_script_translations(), soluția este mecanică. Păstrează-ți șirurile într-un singur .po, compilează .mo pentru PHP și rulează make-json pentru JS.
Fă corect pasul de traducere și ambele ieșiri vor fi în regulă. Fă-l greșit și vei depana panouri goale ale editorului o după-amiază întreagă.
Ești gata să-ți traduci șirurile JSON și PHP din WordPress dintr-o singură sursă curată? Încearcă SimplePoTranslate gratuit — nu este necesar un card de credit. Nivelul gratuit traduce fișiere
.poși.potreale cu Syntax Locking sigur pentru placeholder-uri, astfel încât șirurile editorului tău de blocuri să fie livrate corect.