FunkcjeWtyczkaCennikZasoby
Zmień język
ZasobyTłumaczenie JSON WordPress: Tłumaczenie JavaScript edytora bloków

Tłumaczenie JSON WordPress: Tłumaczenie JavaScript edytora bloków

SimplePoTranslate Team27 maja 2026
Tłumaczenie JSON WordPress: Tłumaczenie JavaScript edytora bloków

Przetłumaczyłeś swoją wtyczkę. Ciągi PHP wyświetlają się idealnie w ustawieniach administratora, szablonach frontendowych, powiadomieniach e-mail – wszystko jest zlokalizowane. Potem otwierasz edytor bloków, a każda etykieta w twoim niestandardowym bloku Gutenberga jest uparcie, drwiąco angielska. Przycisk „Add Item”, nagłówki panelu inspektora, tekst zastępczy. Twój plik .mo jest załadowany. Dlaczego więc te ciągi znaków się nie tłumaczą?

Ponieważ od WordPressa 5.0 i pojawienia się Gutenberga, ciągi znaków JavaScript w ogóle nie pochodzą z twojego pliku .mo. Wymagają one całkowicie oddzielnego pliku tłumaczenia JSON WordPress dla każdego skryptu – a jeśli go nie wygenerujesz, twój edytor bloków pozostanie w języku angielskim, bez względu na to, jak kompletny jest twój plik .po. Jest to jedna z najczęstszych i najbardziej mylących luk w lokalizacji we współczesnym rozwoju WordPressa. Ten przewodnik wyjaśnia dokładnie, dlaczego tak się dzieje, jak działa system tłumaczenia JSON, nazwy plików z hashem MD5, które zaskakują każdego, oraz pełny zestaw narzędzi do naprawienia tego problemu.

Dlaczego ciągi znaków w edytorze bloków pozostają angielskie

Krótka odpowiedź: PHP i JavaScript używają dwóch zupełnie różnych systemów dostarczania tłumaczeń w WordPressie, a twój plik .mo zasila tylko ten dla PHP.

Dwa systemy tłumaczeń, jedna wtyczka

Kiedy WordPress uruchamia load_plugin_textdomain(), wczytuje skompilowany plik .mo do pamięci PHP. Każde wywołanie __(), _e() i _x() w twoim kodzie PHP szuka tam swojego tłumaczenia. Działa to, ponieważ PHP renderuje po stronie serwera – dane .mo są dostępne w tym samym procesie.

JavaScript jest inny. Kod twojego bloku działa w przeglądarce, długo po zakończeniu działania PHP. Nie może on sięgać do pliku .mo po stronie serwera. Zamiast tego, pakiet @wordpress/i18n – odpowiednik Gettext dla JS, udostępniający __(), _x() i sprintf() twoim skryptom – oczekuje, że tłumaczenia zostaną dostarczone jako ładunek JSON dołączony do konkretnego skryptu, który ich potrzebuje.

Co się dzieje z nieprzetłumaczonym ciągiem JS

Więc blok z ciągami znaków takimi jak te:

import { __ } from '@wordpress/i18n';

registerBlockType( 'myplugin/feature-box', {
    title: __( 'Feature Box', 'myplugin' ),
    edit: () => {
        return <Button>{ __( 'Add Item', 'myplugin' ) }</Button>;
    },
} );

nigdy nie znajdzie „Feature Box” ani „Add Item” w twoim pliku .mo, ponieważ przeglądarka nigdy nie czyta plików .mo. Te ciągi znaków muszą dotrzeć jako JSON, podłączone do tego konkretnego uchwytu skryptu. Jeśli tego nie skonfigurowałeś, wywołania JS __() po prostu zwracają oryginalny angielski – cicho, bez błędu w konsoli.

Łączenie tłumaczeń JSON z wp_set_script_translations()

Mostem między twoim skryptem a jego tłumaczeniami JSON jest pojedyncza funkcja PHP: wp_set_script_translations(). Odpowiedź na pytanie „skąd WordPress wie, który plik JSON należy do którego skryptu” brzmi: ty mu to mówisz, rejestrując skrypt, a następnie deklarując jego domenę tekstową i folder, w którym znajduje się JSON.

Rejestrowanie skryptu i jego folderu tłumaczeń

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

Kiedy edytor ładuje myplugin-editor, WordPress wie teraz, aby szukać w folderze languages/ pliku JSON pasującego do tego skryptu i ustawień regionalnych bieżącego użytkownika. Jeśli go znajdzie, wstrzykuje tłumaczenia przed uruchomieniem twojego skryptu, a wywołania JS __() rozwiązują się poprawnie. Przekazany uchwyt musi dokładnie odpowiadać zarejestrowanemu skryptowi – niedopasowany lub brakujący uchwyt to druga najczęstsza przyczyna cichego niepowodzenia tłumaczeń.

Nazwa pliku z hashem MD5, której nikt się nie spodziewa

Oto szczegół, który dezorientuje prawie każdego. Plik JSON, którego szuka WordPress, nie jest nazwany w sposób uporządkowany, jak myplugin-fr_FR.json. Nazywa się go z użyciem hasza MD5 ścieżki źródłowej skryptu:

Dekodowanie wzorca nazwy pliku

myplugin-fr_FR-a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6.json

Wzór to {textdomain}-{locale}-{md5}.json, gdzie hash to MD5 względnej ścieżki do pliku skryptu (na przykład build/index.js) zarejestrowanego. WordPress oblicza ten hash w czasie wykonania, aby znaleźć odpowiedni plik JSON dla odpowiedniego skryptu. Jeśli ręcznie nazwiesz swój plik, WordPress go nie znajdzie, a ty będziesz przekonany, że system jest zepsuty, podczas gdy on po prostu szuka innej nazwy pliku.

Nie obliczasz hasha samodzielnie. Robi to za ciebie polecenie WP-CLI i18n, dlatego właśnie musisz używać narzędzi, zamiast ręcznie tworzyć te pliki. Zrozumienie, że hash istnieje, pozwala jednak zaoszczędzić godziny, gdy plik JSON jest obecny w languages/, ale nadal jest ignorowany – prawie zawsze jest to niezgodność hasha nazwy pliku, ponieważ zmieniła się ścieżka skryptu.

Pełny przepływ pracy: od make-pot do make-json

Dobra wiadomość jest taka, że zachowujesz tłumaczenia w tych samych plikach .po, których już używasz. JSON jest artefaktem pochodnym generowanym na końcu. Odpowiedź na pytanie „czy mam utrzymywać ciągi JS oddzielnie” brzmi nie – żyją one w tych samych plikach .pot/.po co twoje ciągi PHP, a jedno dodatkowe polecenie rozdziela ciągi JS na JSON.

Czteroetapowa procedura

Oto kompletna procedura:

# 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

make-pot z kroku 1 jest wystarczająco inteligentny, aby skanować zarówno twoje pliki .php, jak i źródła .js/.jsx, więc jeden plik .po na locale zawiera wszystko. make-json z kroku 4 czyta każdy przetłumaczony plik .po, znajduje wpisy pochodzące z plików JavaScript i zapisuje jeden poprawnie haszowany plik JSON na skrypt. Flaga --no-purge zachowuje również ciągi JS w twoim pliku .po, dzięki czemu późniejsze make-mo ich nie traci – bez niej make-json usuwa wpisy JS z pliku .po, co zaskakuje osoby, które uruchamiają polecenia w złej kolejności.

Wygenerowany plik JSON wygląda jak zestaw tłumaczeń w formacie 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 odczytuje locale_data i przekazuje je do @wordpress/i18n przed uruchomieniem twojego skryptu. Teraz __( 'Add Item', 'myplugin' ) w przeglądarce zwraca Ajouter un élément, a twój edytor bloków jest wreszcie zlokalizowany.

Czym różni się to od i18next JSON

Oba systemy używają JSON, oba celują w JavaScript, a to powierzchowne podobieństwo powoduje prawdziwe zamieszanie. Nie są one zamienne. JSON edytora bloków WordPressa to ładunek pochodzący z Gettext, haszowany MD5, dla każdego skryptu, konsumowany przez @wordpress/i18n. i18next JSON to płaski lub zagnieżdżony plik klucz-wartość konsumowany przez react-i18next lub next-intl, z własną składnią {{interpolation}} i konwencjami kluczy liczby mnogiej.

Jeśli pracujesz w czystym React lub Next.js poza WordPressem, chcesz podejścia i18next, które opisujemy w tłumaczeniu i18next JSON w React i Next.js. Wewnątrz WordPressa chcesz skorzystać z powyższego przepływu pracy make-json. Mieszanie ich – na przykład, ręczne pisanie płaskiego JSON w stylu i18next i oczekiwanie, że wp_set_script_translations() go załaduje – po prostu nie zadziała, ponieważ WordPress szuka haszowanego formatu Jed, a nie dowolnych par klucz-wartość.

Jedno źródło, każdy format, którego potrzebujesz

Kruchość tego wszystkiego tkwi w kroku tłumaczenia, który znajduje się pośrodku. Twój plik .po zasila zarówno .mo (PHP), jak i JSON (JavaScript), więc jedno nieudane tłumaczenie – zniekształcony %s, uszkodzony tag <strong>, zmieniona forma liczby mnogiej – zatruwa oba wyjścia jednocześnie. A ponieważ ciągi JS są ładowane asynchronicznie w przeglądarce, błąd strukturalny często objawia się jako pusta etykieta lub twarde zawieszenie, a nie jako eleganckie rozwiązanie awaryjne.

Jedno przesłanie, pokryte PHP i JavaScript

Właśnie w tym miejscu pipeline tłumaczeń, który rozumie strukturę Gettext, zyskuje swoje miejsce. SimplePoTranslate przyjmuje jeden plik źródłowy .po lub .pot i generuje czysty, przetłumaczony wynik w wielu formatach z jednego przesłania.po, .mo, .json, .php i .xliff – dzięki czemu nie musisz łączyć oddzielnych narzędzi dla warstw PHP i JavaScript. Jego Blokowanie Składni utrzymuje %s, %1$s, {count} oraz inline HTML na właściwym miejscu, co ma podwójne znaczenie dla ciągów edytora bloków, gdzie uszkodzony placeholder może wyłączyć cały panel edytora. Zagłębiamy się w model jednego źródła, wielu wyników w jeden plik wejściowy, pięć formatów wyjściowych.

Nadal uruchamiasz make-json, aby wyprodukować haszowane pliki, których oczekuje WordPress – ten krok jest specyficzny dla WordPressa i pozostaje w twojej kompilacji. Ale samo tłumaczenie, część, która najprawdopodobniej zepsuje twoje ciągi JS, jest obsługiwana przez silnik świadomy kontekstu, a nie przez skrypt typu znajdź-i-zamień.

Podsumowanie

Powód, dla którego twój edytor bloków pozostaje angielski, jest strukturalny, a nie błędem: tłumaczenie JSON WordPress to oddzielny system dostarczania od pliku .mo, stworzony specjalnie dlatego, że przeglądarki nie mogą odczytywać danych Gettext po stronie serwera. Gdy zrozumiesz, że ciągi JavaScript potrzebują haszowanego MD5 JSON generowanego przez wp i18n make-json dla każdego skryptu i podłączonego za pomocą wp_set_script_translations(), rozwiązanie jest mechaniczne. Przechowuj swoje ciągi w jednym pliku .po, kompiluj .mo dla PHP i uruchom make-json dla JS.

Poprawne wykonanie kroku tłumaczenia sprawi, że oba wyjścia będą działać. Zrób to źle, a będziesz debugować puste panele edytora przez całe popołudnie.

Gotowy, aby przetłumaczyć swoje ciągi JSON i PHP WordPress z jednego czystego źródła? Wypróbuj SimplePoTranslate za darmo — karta kredytowa nie jest wymagana. Darmowy plan tłumaczy prawdziwe pliki .po i .pot z bezpiecznym blokowaniem składni (Syntax Locking), dzięki czemu twoje ciągi w edytorze bloków będą poprawne.