How to load translation in JavaScript?

I am struggling to load translation in JavaScript for my simple plugin. Translation works for PHP, but not in JS. What seems to be the problem, how can I debug this?

  1. I have loaded text domain in my plugin method and this works ok. My text domain is instantsearch, locale for my language is hr

    load_plugin_textdomain('instantsearch', FALSE, basename( dirname( __FILE__ ) ) . '/languages/'); // returns true
    var_dump(__('No results', 'instantsearch')); // This shows correct translation for my language
    
  2. I have generated .json file with WP CLI

    wp i18n make-json languages/
    
  3. This gives me new file /myplugin/languages/instantsearch-hr-hash.json. My JS file is assets/instant-search.js and somewhere I have read that I need to manually rename that hash. I just copied that file two times and renamed them to the following just to try it out, so something out of those 3 should be working :)

    instantsearch-hr-47626afcca1bc179bc9eedb6abdc01ff.json
    instantsearch-hr-instant-search.json
    instantsearch-hr-instantsearch.json
    
  4. I have registered the script for translation

    wp_register_script('instant-search', plugins_url('assets/instant-search.js', __FILE__), array('jquery', 'wp-i18n'), false, true);
    wp_enqueue_script('instant-search');
    wp_set_script_translations('instant-search', 'instantsearch', plugins_url('languages', __FILE__));
    
  5. In the script at the very top I have tried this, but it doesn't give me translation like in PHP, it just shows english default string

    console.log(wp.i18n.__('No results', 'instantsearch'));
    
  6. Here is example of json

    {"translation-revision-date":"2019-12-31 13:41+0100","generator":"WP-CLI\/2.4.0","source":"assets\/instant-search.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"hr","plural-forms":"nplurals=3; plural=(n%10==1  n%100!=11 ? 0 : n%10=2  n%10=4  (n%10012 || n%10014) ? 1 : 2);"},"No results":["Nema prona\u0111enih rezultata"]}}}
    
  7. I know I can use wp_localize_script() to move string from PHP to JS but from WP 5.* we should be able to do it

Topic textdomain translation Wordpress javascript

Category Web


Inside the wp_set_script_translations function, you use plugins_url('languages', __FILE__) which is not the correct path.

You should use plugin_dir_path(__FILE__) . 'languages/'


I'll leave it here. Perhaps it will help someone. I had the same issue. I did all steps and all looked working, but in JS __('Hello world', 'textdomain'); didn't work.

There are a lot of recommendations about the JSON file for example to use 'nl' instead 'nl_NL', etc. For today (2020.08.06) you shouldn't change a json-file in any way except its name as custom_dir/{domain}-{locale}-{handle}.json.

The base steps:

  1. PHP code:
load_theme_textdomain( 'textdomain', get_template_directory() . '/languages' );
// ...
wp_enqueue_script( 'scripts', asset_url( 'js/app.js' ), [ 'jquery', 'wp-i18n' ], null, true );
wp_set_script_translations( 'scripts', 'textdomain', get_template_directory() .'/languages/js' );
  1. I use the Poedit application for creating & translating the nl_NL.po file.

  2. With WP-CLI I generate wp i18n make-json ./languages ./languages/js --no-purge --pretty-print a json-file and I reneme it to ./languages/js/textdomain-nl_NL-scripts.json.

The essential thing: The author's mistake is plugins_url('languages', __FILE__) in wp_set_script_translations();. My mistake was a simple get_template_directory_uri() instead of get_template_directory(). But the function requires "$path The full file path to the directory containing translation files".

All you need is placed here: https://developer.wordpress.org/block-editor/developers/internationalization/.


I was having the same problem and this is how I solved it:

First, the generated JSON file has some errors. You need to update where it says messages with your text domain. There are three places where that needs to be changed. I also had to change the lang attribute to be all lowercase with a dash. Here are the fields I changed:

{
  "domain": "my-text-domain",
  "locale_data": {
    "my-text-domain": { // Instead of "messages"
      "": {
        "domain": "my-text-domain",
        "lang": "es-es"
      },
      ...
    }
  }
}

Second, the file name with the md5 hash tends to have the wrong md5 hash, so it's best to rename the file to {domain}-{locale}-{script-name}.json, so mine became my-text-domain-es_ES-my-script-name.js.

Third, the wp_set_script_translations function needs to be called with the right path, and attached to the right hook. This is what I had to do, since I was localizing an admin-side script:

function enqueue_scripts() {
    wp_set_script_translations( 'script-name', 'my-text-domain', plugin_dir_path( dirname(__FILE__) ) . 'languages' );
}
add_action( 'admin_enqueue_scripts', 'enqueue_scripts' );

Try echoing out the value of plugin_dir_path( dirname(__FILE__) ) . 'languages' to make sure you're getting the path where your translation files are.

Once I sorted out all of these little details, my translations started working, so I hope this helps someone else!

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.