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 :)

  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_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%100<12 || n%100>14) ? 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

  • you use wp_register_script instead of wp_enqueue_script then translation are not loaded. then in wp_set_script_translations you have to set the path look in the documentation
    – Kaperto
    Dec 31 '19 at 15:06
  • I use both, first I register and then a little bit later enqueue. I have updated my code. I tried setting wp_set_script_translation with a path (which correctly points to languages directory in plugin) but unfortunately still no success
    – Marko
    Dec 31 '19 at 15:46
  • I tried you json content with a file instantsearch-hr-instant-search.json and it works. then I think you are near of having a good result but I don't know how to help you.
    – Kaperto
    Dec 31 '19 at 16:43
  • 2
    I'm having the same issue. Did you ever solve this? May 1 '20 at 20:57
  • The same and it looks like the @JosiahSprague's answer doesn't work for me. I tried a lot variations. In the page, I can see an inline script and empty i18n JSON '{ "locale_data": { "messages": { "": {} } } }'. It's right above my app.js. wp_set_script_translations() returns true. get_locale() is 'nl_NL' and is correct. Aug 5 '20 at 18:22

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!

  • It doesn't work for me. I read a lot of articles and posts. It should work, but... I can't figure out where I'm wrong. Perhaps, now you can add some additional ingo by the question. Aug 5 '20 at 18:38

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/.


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/'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.