While developing my first more complex blocks I ran into different issues. One of them was extracting the strings for my translations. In my previous blog post I showed you how to get those strings for PHP files. Those methods also work for the JavaScript files as the use “the same functions”, or at least aliases that have the same name.
Translate strings in a Gutenberg block
Let’s start to look at an example of a string translation in a block. This example comes straight from the Create a Block Tutorial and shows an “Edit” component:
import { TextControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
export default function Edit( { attributes, className, setAttributes } ) {
return (
<div className={ className }>
<TextControl
label={ __( 'Message', 'gutenpride' ) }
value={ attributes.message }
onChange={ ( val ) => setAttributes( { message: val } ) }
/>
</div>
);
}
The __
function is imported from the @wordpress/i18n
component. This code works perfectly fine for translating the string in line 8. It only fails when you try to extract this string into PO file.
Compiled JavaScript file
But why does this example not work when trying to extract the strings? When you work with components like this you usually split up your JavaScript code into multiple files. You then import all those files into a main JavaScript file and then you build the JavaScript file that is used in the browser with something like @wordpress/scripts
like explained in the JavaScript Build Setup chapter. This will then create a file build/index.js
and the string from the example above will look like this:
// ...
/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n");
// ...
function Edit(_ref) {
var attributes = _ref.attributes,
className = _ref.className,
setAttributes = _ref.setAttributes;
return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("div", {
className: className
}, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__["TextControl"], {
label: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__["__"])('Message', 'block-i18n'),
value: attributes.message,
onChange: function onChange(val) {
return setAttributes({
message: val
});
}
}));
}
In line 11 we will find the string again. But it’s not wrapped in a plain __
function. Instead the complied JavaScript files uses some weird function names from the components imported by webpack. As this function/syntax is not known to the wp i18n make-pot
command or the X-Poedit-KeywordsList
that Poedit is using, the string will not be found when parsing the files.
Solution: Use a different syntax to import components
There is an easy fix for that. You can import components in different ways. Simply replace the import of the i18n
functions in line 2 with this “import”:
const { __ } = wp.i18n;
This will then result in the following complied JavaScript file which will use the plain __
function (in line 10) that is known to the parser:
// ...
var __ = wp.i18n.__;
function Edit(_ref) {
var attributes = _ref.attributes,
className = _ref.className,
setAttributes = _ref.setAttributes;
return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("div", {
className: className
}, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__["TextControl"], {
label: __('Message', 'block-i18n'),
value: attributes.message,
onChange: function onChange(val) {
return setAttributes({
message: val
});
}
}));
}
Interestingly, when I removed the import
without replacing it, it worked as well. That might be due to the fact that the __
function was already imported by another import and was therefor available. But I would recommend to always define which external components and functions you use in your own JavaScript files. In the same way you can also replace the first line like this:
const { TextControl } = wp.components;
Other tutorials always use this method to import components from WordPress/Gutenberg, so I would highly recommend to do it like this as well. I haven’t had an issue with them and the result complied JavaScript files were even a little smaller in size.
Conclusion
Translating strings in a Gutenberg block (or similar JavaScript code for WordPress) is super easy, as you can simply use the same functions you already know from PHP. But if you do the imports “wrong”, extracting the strings for Poedit does not work.
As I have seen some plugins who do it this way and still have working translations there might be a way to extract them anyways. If you know how they do it, I would highly appreciate if you can leave a comment explaining us, how it works.
Hi Bernhard. the latest wp-scripts routines already support internationalisaion and localisation of Gutenberg plugins. I used the techniques in my sb-children-block plugin. See https://github.com/bobbingwide/sb-children-block/issues/5
Thanks for the tip! I’ve honestly haven’t tested the one bundled in wp-scripts. I’ve just recently saw another project with something similar. But this is using the WP-CLI, right? For me, this was also not fully working. But maybe I ave to give it another try.