wp_localize_script. While this system works great it has some limitations.
- You add your text in the React components where it is used so you don’t have to map objects to strings.
- Translations need only be loaded when the site is in a language you have translations for instead of loading for every language.
- Translation calls are done during translation generation not during page load which improves performance.
The TypeScript Problem
The available tools provided from WP-CLI for translating have the following assumptions:
- Each JS file is a single file per block and should therefore have a separate translation file per JS file.
- All source files have a
- A WordPress install must be available which adds complexity to Continuous Delivery.
As you know, if you are reading this, using a modern Webpack based application with TypeScript does not fit into those assumptions.
The maintainers of the WP-CLI command are not working on a solution because of an underlying dependency limitation.
There are some suggested workarounds to compile your application first then run the WP-CLI commands against it. This was not reasonable for us for the following reasons:
- Our Webpack compiler will obfuscate the finished JS to the point that the WP-CLI tools do not pick up the calls correctly.
- We prefer to keep our translation process away from our Webpack build process as the translation system is intended to be independent.
This is what you came here for right…?
Let’s recap our goals:
- The system must pull translations out of TypeScript source files. Either
.ts(although TSX would be more prominent).
- The generation of the finished JSON files must be able to be run during Continuous Delivery.
- The generation of the finished JSON files must be able to run without a WordPress install available.
- The JSON files must be one file per language, not one file per source file.
- The JSON files must contain only translations located within TypeScript files and not PHP required translations.
Generating the .PO files
To enter the translations into the
.po files we use a tool called Poedit. Since we are already using Poedit as part of the translation process, it was a no brainer to also use Poedit to generate the
Out of the box, Poedit does not support TypeScript extensions. TypeScript support may be added using the following:
- File -> Preferences
- Tab -> Extractors
List of extensions:
An item in keyword list:
An item in input files list:
Source code charset:
Now you may click the “Update from code” button like normal and your
.po files will fill with translations within TypeScript. Enter your translations, hit save, and you’re good to go.
Generating the JSON translation files
For this part we create a custom PHP script which takes the finished translation from the
.po files and turns them into something WordPress can understand.
First we need Gettext. Gettext is a library for managing translations. It is the same library used by WP-CLI as well as WordPress Core. We install it using Composer.
This will generate a composer.json which looks like this:
Next create a PHP script. This could be named anything you like, but we named ours
This PHP script does the following tasks:
- Loops through every
.pofile found in the
- Generates a matching
.jsonfile for each found
- Returns a code to let the runner know if any of the tasks failed.
The only change you’ll need to make is update the
RELATIVE_PATH to match where your finished JS (non min) file is located relative to your plugin or theme. This is important because it controls the hash included in the
.json file names. If the
RELATIVE_PATH does not match where the file is located when it is enqueued via
wp_register_script, WordPress won’t load it.
For more information check out the source code of
Running the PHP script is simple:
Integrating with your build system
The system wouldn’t be complete if we had to manually run the PHP script before each release. You can add the commands to whatever Continuous Delivery system you use. For these purposes we’re going to use GitHub Actions.
Add the following jobs to your existing action configuration and the JSON files will auto generate during each release.
Notice how we set a
PHP_VERSION environmental variable? That is an optional way to manage which PHP version will be install and used for the PHP commands.
That’s it! You’re now translating your TypeScript.