WordPress’ i18n foreign language translation functionality does not work as expected in JavaScript when a plugin utilizes ES6 modules. The translation data, which should be injected into the webpage, is removed after the script_loader_tag
filter is applied. This behavior prevents JavaScript/.json translations from being displayed.
Context:
WordPress version 6.2.2. This issue occurs specifically in the context of plugin development with ES6 modules and i18n language translations.
We are aware that new functions wp_register_script_module
and wp_enqueue_script_module
were introduced in WordPress v6.5, which directly support ES6 modules. However, as plugin developers, we want to maintain backward compatibility and do not want WordPress v6.5 to be our minimum required version at this time. Therefore, we’re utilizing the existing method to register and enqueue our scripts.
Plugin Setup:
Here is the relevant code used to register and enqueue the ES6 module in our plugin:
// Enqueue scripts and styles
function ac_test_buttons_2_enqueue_scripts() {
wp_enqueue_style('ac-test-buttons-2-style', plugin_dir_url(__FILE__) . 'dist/css/styles.css');
// Enqueue the ES6 module and include wp-i18n as a dependency
wp_enqueue_script('ac-test-buttons-2-script', plugin_dir_url(__FILE__) . 'dist/js/click-handlers.js', array('wp-i18n'), null, true);
// Set the script to be an ES6 module
wp_script_add_data('ac-test-buttons-2-script', 'type', 'module');
// Ensure that translations are available for the JS
wp_set_script_translations('ac-test-buttons-2-script', 'ac-test-buttons-2', plugin_dir_path(__FILE__) . 'languages');
}
add_action('wp_enqueue_scripts', 'ac_test_buttons_2_enqueue_scripts');
The Problem:
WordPress’ translation system injects the translation data into the webpage markup using <script>
tags. However, when working with ES6 modules, the translation script does not get injected into the page.
This is due to our script tag being first modified from type="module"
to type="text/javascript"
. Then subsequently, the script_loader_tag
filter is applied, which changes the type="text/javascript"
translation script back to type="module"
, effectively removing the translation data.
Investigation:
We traced the issue to the wp-includes/class-wp-scripts.php
, specifically within the do_item()
function. At around line 605, you will find the following filter:
$filtered_tag = apply_filters('script_loader_tag', $tag, $handle, $src);
Before this filter is applied, the script tag contains the translation data with type="text/javascript"
. After applying the filter, the tag is modified to type="module"
, and the translation data is dropped. Consequently, the translations are not echoed to the page.
Below are the relevant log entries showing this behavior:
Log Entries:
[02-Oct-2024 17:11:54 UTC] do_item(): Built tag for handle: ac-test-buttons-2-script, value of $tag: <script type="text/javascript" id="ac-test-buttons-2-script-js-translations">
/* <![CDATA[ */
( function( domain, translations ) {
var localeData = translations.locale_data[ domain ] || translations.locale_data.messages;
localeData[""].domain = domain;
wp.i18n.setLocaleData( localeData, domain );
} )( "ac-test-buttons-2", {
"translation-revision-date": "2024-10-01 11:00-0000",
"domain": "ac-test-buttons-2",
"locale_data": {
"messages": {
"": {
"domain": "ac-test-buttons-2",
"lang": "de",
"plural-forms": "nplurals=2; plural=(n != 1);"
},
"You have clicked me!": [ "Du hast mich angeklickt!" ]
}
}
});
/* ]]> */
</script>
<script type="text/javascript" src="https://localhost:8100/wp-content/plugins/ac-test-buttons-2/dist/js/click-handlers.js" id="ac-test-buttons-2-script-js"></script>
[02-Oct-2024 17:11:54 UTC] do_item(): After applying script_loader_tag filter for handle: ac-test-buttons-2-script, value of $filtered_tag: <script type="module" src="https://localhost:8100/wp-content/plugins/ac-test-buttons-2/dist/js/click-handlers.js"></script>
[02-Oct-2024 17:11:54 UTC] do_item(): Echoing tag for handle: ac-test-buttons-2-script
(Log show same handle with type changing and ID being dropped.)
Reproducing the Issue:
You can confirm this by adding the following logging within the core WordPress code in the wp-includes/class-wp-scripts.php
file inside the do_item()
function:
$tag = $translations . $cond_before . $before_script;
$tag .= wp_get_script_tag($attr);
$tag .= $after_script . $cond_after;
error_log("do_item(): Built tag for handle: $handle, value of \$tag: $tag");
// Apply the script loader filter and log the result
$filtered_tag = apply_filters('script_loader_tag', $tag, $handle, $src);
error_log("do_item(): After applying script_loader_tag filter for handle: $handle, value of \$filtered_tag: $filtered_tag");
Conclusion:
The translations are being stripped when the script_loader_tag
filter is applied, resulting in the loss of translation functionality for ES6 module-based scripts. This raises a concern for plugin developers working with ES6 modules who rely on WordPress’ i18n system to handle translations. We would appreciate further guidance or clarification as to whether this behavior is intended, and if not, a potential fix for preserving translation data in this scenario.
Could be possible to create multiple modules with the keyword shortcode for an automatic web?
It is possible like this:
[content-egg-block template=offers_list modules=Amazon,Ebay keyword=”phone”]
If not, could you tell how can be possible?
Thanks
]]>They appear but formatting is off. Might be a color scheme issue?
]]>Can you please confirm which specific Jetpack modules are critical for the WooCommerce app to function properly? I would like to ensure that I only keep the essential modules active to avoid any issues with the app while optimizing my website’s performance.
Thank you in advance for your assistance.
Best regards,
Roman
Fatal error: Uncaught Error: Call to undefined function wpcf7_include_module_file() in /home/customer/www/ruralvtrealestate.com/public_html/wp-content/plugins/contact-form-7/modules/constant-contact/constant-contact.php:8 Stack trace: #0 /home/customer/www/ruralvtrealestate.com/public_html/wp-content/plugins/contact-form-7/load.php(72): include_once() #1 /home/customer/www/ruralvtrealestate.com/public_html/wp-content/plugins/contact-form-7/load.php(38): WPCF7::load_module('constant-contac...') #2 /home/customer/www/ruralvtrealestate.com/public_html/wp-content/plugins/contact-form-7/load.php(105): WPCF7::load_modules() #3 /home/customer/www/ruralvtrealestate.com/public_html/wp-includes/class-wp-hook.php(305): wpcf7() #4 /home/customer/www/ruralvtrealestate.com/public_html/wp-includes/class-wp-hook.php(331): WP_Hook->apply_filters(NULL, Array) #5 /home/customer/www/ruralvtrealestate.com/public_html/wp-includes/plugin.php(476): WP_Hook->do_action(Array) #6 /home/customer/www/ruralvtrealestate.com/public_html/wp-settings.php( in /home/customer/www/ruralvtrealestate.com/public_html/wp-content/plugins/contact-form-7/modules/constant-contact/constant-contact.php on line 8.
I restored backup to solve the problem, but would like to know when this is fixed so I can safely update the plugin.
]]>