• Resolved financialcalculators

    (@financialcalculators)


    Summary:

    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="http://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="http://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.

Viewing 2 replies - 1 through 2 (of 2 total)
Viewing 2 replies - 1 through 2 (of 2 total)

The topic ‘JavaScript Translations Not Working with ES6 Modules in WordPress’ is closed to new replies.