Repository navigation
I18N: Print translations for the script modules that classic scripts depend on - #14260
jorgefilipecosta wants to merge 2 commits into
Conversation
…ies into a helper. Moves the code that collects the script module dependencies of classic scripts out of `WP_Script_Modules::get_import_map()` into a private `get_classic_script_module_dependencies()` method, so other methods can use the same list. There is no change in behavior.
…depend on. `WP_Script_Modules::print_script_module_translations()` only covered the enqueued script modules and their dependencies. A script module that only a classic script imports, declared in the classic script's `module_dependencies`, is added to the import map and loads, but its translations were never printed, so its strings showed untranslated. The method now also covers the script module dependencies of classic scripts and their dependencies: the same script modules the import map adds for classic scripts, collected by the same helper. A script module that is both enqueued and imported by a classic script gets its translations printed once, and a missing script module dependency still triggers a single `_doing_it_wrong()` notice.
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
| /* | ||
| * Collect the IDs of the script modules that can load on the page: the enqueued ones, the ones that classic | ||
| * scripts depend on, and the dependencies of both. | ||
| */ | ||
| $classic_script_module_dependencies = $this->get_classic_script_module_dependencies(); | ||
|
|
||
| $module_ids = array_unique( | ||
| array_merge( | ||
| $this->get_sorted_dependencies( $this->queue ), | ||
| $classic_script_module_dependencies, | ||
| array_keys( $this->get_dependencies( $classic_script_module_dependencies ) ) | ||
| ) | ||
| ); |
There was a problem hiding this comment.
print_script_module_data() already builds "every module that can load" from the queue plus the import map keys:
wordpress-develop/src/wp-includes/class-wp-script-modules.php
Lines 1063 to 1076 in 4fa8850
The same works here and gives the same set: the import map is the classic script module dependencies plus get_dependencies() of the queue and of those, so only the queue itself needs adding. The one difference is a module whose filtered src is '', which cannot load anyway. This keeps the import map, data and translations in lockstep by construction, and the get_classic_script_module_dependencies() extraction is no longer needed (the once-per-handle notice guard still is, since get_import_map() would then run three times).
| /* | |
| * Collect the IDs of the script modules that can load on the page: the enqueued ones, the ones that classic | |
| * scripts depend on, and the dependencies of both. | |
| */ | |
| $classic_script_module_dependencies = $this->get_classic_script_module_dependencies(); | |
| $module_ids = array_unique( | |
| array_merge( | |
| $this->get_sorted_dependencies( $this->queue ), | |
| $classic_script_module_dependencies, | |
| array_keys( $this->get_dependencies( $classic_script_module_dependencies ) ) | |
| ) | |
| ); | |
| /* | |
| * Collect the IDs of the script modules that can load on the page: the enqueued ones and their dependencies, | |
| * and the ones in the import map, which includes the script modules that classic scripts depend on. | |
| */ | |
| $module_ids = array_unique( | |
| array_merge( | |
| $this->get_sorted_dependencies( $this->queue ), | |
| array_keys( $this->get_import_map()['imports'] ) | |
| ) | |
| ); |
There was a problem hiding this comment.
Yes, I think the biggest issue after we have this PR is that there are two loops over all reachable modules, print_script_module_translations and print_script_module_data, which should loop exactly the same way, but they don't. get_sorted_dependencies is used inconsistently: one loop has, the other doesn't. And the classic dependencies are not sorted at all, although they should be.
get_import_data loops differently, but not differently enough to have a completely custom code. It subtracts the already queued modules and it also skips modules with src=''. The additional src='' check, maybe it should be a validity check that applies to all modules? I don't think we support inline modules.
Unifying the translations and data behaviors in important, even a blocker, get_import_data can remain custom.
| * @since 7.2.0 | ||
| * @var string[] | ||
| */ | ||
| private $classic_scripts_with_missing_module_dependencies = array(); |
There was a problem hiding this comment.
Naming nit: let's call these just "scripts", not "classic scripts". Everything else in the codebase calls them "scripts". The WP_Scripts class, functions like wp_register_script, actions like admin_print_scripts, etc.
Right now
WP_Script_Modules::print_script_module_translations()only prints the translations of the enqueued script modules and their dependencies. Since WordPress 7.0, a classic script can also declare the script modules it imports in itsmodule_dependenciesdata, andget_import_map()adds those script modules and their dependencies to the import map. So a script module that only a classic script imports loads fine, but its translations are never printed, and its strings show in English even when the language pack translates them.This PR:
module_dependenciesout ofget_import_map()into a privateget_classic_script_module_dependencies()method, so the import map and the translations always cover the same script modules.print_script_module_translations()also print the translations of the script modules that classic scripts depend on, and of their dependencies. A script module that is both enqueued and a classic script's dependency is printed once._doing_it_wrong()notice for missing script modules fire once per classic script. The walk already runs twice per page, fromprint_import_map()andprint_script_module_data(), so the notice fired twice, and the new caller would make it three times.Some notes:
@wordpress/core-actionsscript modules gutenberg#84643 moves the DataViews core actions into@wordpress/core-actionsscript modules that the classicwp-editorscript imports, and Fields API gutenberg#83368 does the same for the core fields, which the Fields API (Add entity fields: API, registry, endpoint #13911) adds towp-editor'smodule_dependencies. Today their strings are translated because they are bundled intowp-editor. Without this fix, strings like "Rename…", "Trash…" and "Export as JSON" would show in English once they move to script modules. The same applies to the field modules that plugins register.Before
The test page of the e2e test in the Gutenberg backport, where one line comes from an enqueued script module and the other from a script module that only a classic script imports:
After
Testing Instructions
If Gutenberg is active, deactivate it, since Script Modules: Fix missing translations of script modules gutenberg#84651 fixes the same issue in the plugin.
Save this snippet as
wp-content/mu-plugins/module-translations-test.php(src/wp-content/mu-plugins/in a wordpress-develop checkout). It registers atest/helloscript module that only a classic script imports, gives it a translation, and makes it show__( 'Hello' )in an alert on the Dashboard:Open the Dashboard. On trunk, the alert says "Hello". With this PR, it says "Hello (translated)".
Delete the snippet and run
npm run test:php -- --group script-modules.Gutenberg backport: WordPress/gutenberg#84651.
Trac ticket: TBD
Use of AI Tools
AI assistance: Yes
Used for: drafting the fix, the tests and this description; reviewed and edited by me.
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.