New! JavaScript i18n support in WordPress 5.0

For years, internationalization (i18n) has been a thing that has been pretty well supported in WordPress when it comes to PHP development. For PHP, WordPress already provides all the tools necessary to make it as easy as possible to localize WordPress core, themes and plugins to any language. Today we are bringing the same capabilities to JavaScript development for WordPress.

How does it work?

When registering your scripts you can add wp-i18n as a dependency to allow you to add translatable strings as you would in PHP:

These functions mirror their PHP counterparts and can be used in exactly the same manner.

The final step is to tell WordPress your script contains translations and of which domain, this is to allow WordPress to selectively load only the necessary translations to ensure everything is as fast as can be:

wp_set_script_translations( 'my-handle', 'my-domain' );

Advanced usage

Right now it’s already possible to ship your own translations using the load_textdomain function and passing your own MO file. This is also possible using wp_set_script_translations which accepts an optional third path argument that allows you to tell WordPress to first look elsewhere for translations:

If passed WordPress will first check if a file in the format of ${domain}-${locale}-${handle}.json exists in the given path and use it as the source of translations if so. Alternatively it will also first check the given path for the md5 filename before defaulting to the WordPress languages directory.

If you want to ship your own translation files these should be in the JED 1.x ( .json ) format. GlotPress is able to create these along with other tools such as po2json. Ideally these files should only contain translations that occur within their respective JS files.

Behind the screens

When you upload your plugin or theme to wordpress.org all JS files will automatically be parsed the same as is already being done for PHP files. Any detected translations will be added to translate.wordpress.org to allow the community to cooperate to ensure WordPress, plugins and themes are available in as many languages as possible.

In order to parse all JS files the i18n-command for wp-cli is used. This replaces makepot.php to not only allow picking up translations in JS files but also to audit strings, parse strings only of a specific text domain and even pick up a few strings that weren’t detected by makepot.php. This command is freely available and open-source as makepot.php was and it’s recommended that anyone using makepot.php transition over to this much improved replacement.

Based on these parsed translations Language Packs are generated. Traditionally these used to only contain PO and MO files, one pair for each locale. In order to selectively load only the necessary translations regardless of whether it’s used or not a few more files are being added, one JSON file for every JS file that contains translations per locale.

When parsing JS files for translations we don’t know which handle is used to register that file so we’ve had to use an alternate mechanism to find the translations belonging to each file. To do this we’re using the md5 of the relative path of each file. This is appended to the usual name of ${domain}-${locale} in the form of ${domain}-${locale}-${md5}.json.

When you set script translations for a handle WordPress will automatically figure out the relative md5 hash of your source file, check to see if a translations file exists and if so ensure that it’s loaded into wp.i18n before your script runs.

Plugin and theme support

Translation and Language packs support for plugins and themes that are hosted on the repo is expected in the upcoming weeks. The patches are ready and waiting for commit. Plugin and theme authors are encouraged to start using wp-i18n in their JavaScript projects.

It’s true that you won’t be able to rely on wp_set_script_translations for older versions of WP unless you backport it. However, some plugins (including Yoast SEO) already ship JavaScript translations for quite some time. In the end it’s a matter of having the JSON translations available when you initialize wp-i18n.

We will probably move over to the new core implementation though once 5.0 lands. I think we’ll go with the backport over our current implementation, because it’s future compatible and gives the benefit of JS language packs.

When you choose to backport, please check if the functions you’re backporting weren’t set already in order to not collide with other plugins who might want to do the same thing. Might seem superfluous, but I’ve seen that go wrong more than once.

This looks like a great engineering effort — congrats to those involved!

@omarreiss Can you help explain when one would choose to use these new JS-native l18n functions in themes and plugins going forward (after 5.0 and into the future), and when one should instead use the `wp_localize_script()` workflow we’ve had in core for a while?

Are there inherent advantages of each? Will the older approach eventually be deprecated?

There hasn’t been any discussion about deprecating `wp_localize_script` and I can’t see it happening in the foreseeable future. This work in core was mostly done to support using the new `wp.i18n` package because without this work, it’s utility is diminished (and in fact necessary due to Gutenberg using `wp.i18n`).

So with that said, there’s no urgency to switch away from using `wp_localize_script` but definitely recommended to gain the advantages of the new api and in many ways enhances working with translated strings in javascript.