Repository navigation
Extensible Site Editor (v2): wp_set_script_translations() data never reaches wp.i18n – script translations missing for all plugin editor scripts #83769
Description
Description
The Site Editor v2 (admin.php?page=site-editor-v2, extensible site editor / lazy-editor) loads editor assets via the REST endpoint GET /wp-block-editor/v1/assets and injects <script>/<style> tags client-side. The server-side collector, WP_REST_Block_Editor_Settings_Controller::process_assets() (lib/experimental/class-wp-rest-block-editor-settings-controller.php), serializes each script as {src, deps, version, in_footer} plus inline_scripts (before/after + print_extra_script() data), but it never calls WP_Scripts::print_translations().
As a result, no wp.i18n.setLocaleData() payload is emitted for any script that has a text domain registered via wp_set_script_translations() – which is what register_block_script_handle() does automatically for every editorScript declared in block.json (wp-includes/blocks.php). wp.i18n.getLocaleData( $domain ) is empty and all __()/_x()/sprintf() calls in plugin block editor code return the English originals, even though the Jed JSON translation file exists and is correctly resolved by load_script_textdomain().
This affects every plugin block editor script – not just one plugin. The same gap presumably applies to script modules (load_script_module_textdomain is likewise never invoked for the script_modules import map).
Step-by-step reproduction instructions
-
Enable the "Extensible Site Editor" experiment (or open
admin.php?page=site-editor-v2directly – the page is registered unconditionally). -
Register a block whose editor script has translations:
add_action( 'init', function () { register_block_type( 'my-plugin/demo', array( 'api_version' => 3, 'editor_script' => 'my-plugin-demo', ) ); wp_register_script( 'my-plugin-demo', plugins_url( 'demo.js', __FILE__ ), array( 'wp-blocks', 'wp-element', 'wp-i18n' ) ); wp_set_script_translations( 'my-plugin-demo', 'my-plugin' ); } );
…with a Jed JSON file present at
wp-content/languages/plugins/my-plugin-{locale}-{md5(src-rel-path)}.json(or in the plugin'slanguages/dir registered viaload_plugin_textdomain()). -
Open the v2 site editor and run in the console:
wp.i18n.getLocaleData( 'my-plugin' ) // => undefined / {} – no messages document.getElementById( 'my-plugin-demo-js-translations' ) // => null – the -js-translations inline script is never emitted
…while the script itself IS injected (
document.getElementById( 'my-plugin-demo-js' )exists). -
Compare with
post.php(post editor) or the v1 site editor (site-editor.php):my-plugin-demo-js-translationsIS printed andgetLocaleData( 'my-plugin' )returns the translated messages.
Expected behavior
Script translations are resolved and emitted for editor scripts loaded via /wp-block-editor/v1/assets, identically to WP_Scripts::do_item() calling print_translations() in the classic editors.
Root cause
get_assets()firesadmin_enqueue_scripts,admin_print_scripts,wp_print_footer_scriptsetc. insideob_start()(lines ~419–431), but onlytext/htmlscript templates are extracted from that output – everything else is discarded.process_assets()then walks$wp_scripts->queue+ dependencies and collectssrc/deps/version,get_inline_script_data()(before/after) andprint_extra_script()– but neverprint_translations(), so the( function( domain, translations ) { …wp.i18n.setLocaleData… } )payload is neither collected nor sent to the client.- Client-side,
packages/lazy-editor(loadAssets) injectsinlineScripts.before[handle]→src→inlineScripts.after[handle]viainjectInlineScript()/loadScript()– the injection channel for translations exists; only the server never fills it.
Suggested fix direction
In process_assets() (or get_assets()), include WP_Scripts::print_translations( $handle, false ) output per script – e.g. appended to inline_scripts.before[$handle], which is the same channel #83762 already uses to deliver wp.blocks.setCategories() before block scripts run, so ordering before src execution is guaranteed. For script modules the equivalent is load_script_module_textdomain() + wp.i18n.setLocaleData injection alongside the script_modules map.
Environment
- Gutenberg plugin 24.0.0 (experiment "Extensible Site Editor" enabled)
- WordPress 7.1.2 / 7.2-alpha
- Theme: block theme (FSE)
Related
- Extensible Site Editor (v2): custom block categories from block_categories_all never reach wp.blocks store #83759 / Extensible Site Editor: Pass custom block categories to the blocks store #83762 – same class of "classic print pipeline skipped by the lazy-editor REST collector" gap (
setCategorieswas fixed by inlining it intoinline_scripts.beforeonwp-block-library; translations need the equivalent treatment per script handle). - Tracking: Extensible Site Editor: 7.2 Iteration Issue Extensible Site Editor: Tracking issue #79895.
Activity