Instead of explaining the theory behind WordPress internationalization (i18n) and localization (l10n), this guide uses a demo plugin to show you:
- How to make a WordPress plugin translation-ready
- How to translate the text strings and integrate these translations into your plugin
You can follow each step of this tutorial by reviewing the code changes that we applied via a Git commit in the demo plugin’s repository.
The Goal for Our Demo Plugin: Making it Multilingual
Our demo plugin, OTGS Foo Banner, displays a banner with a customizable message on the front-end.
Users with access to the site’s backend also see:
We want to make all strings translatable and provide Spanish translations. This will allow users who switch their WordPress admin language to Spanish to also use our plugin in their preferred language.
Step-by-Step Guide to WordPress Plugin Internationalization (i18n) and Localization (l10n)
If you’re not using Composer in your projects yet, initialize it by running composer init
. Then, follow the command-line wizard.
Commit Reference: See commit 6f7a13f on GitHub
To run WP-CLI commands, install WP-CLI via Composer by running:
composer require --dev wp-cli/wp-cli-bundle
Commit Reference: See commit 7a8a68c in GitHub
Adding GetText Calls to PHP Code
In PHP, wrap all the hard-coded strings in gettext WordPress localization functions like __() and _e(). Specify a text domain to uniquely identify translations for your theme or plugin.
- The __() function returns the strings
__('Hello, world!', 'your-text-domain');
- The _e() function echoes a translatable string
_e('Hello, world!', 'your-text-domain');
These functions find the correct translation in the specified locale and domain. If no translation is available, the original string will remain unchanged.
Commit Reference: See commit cae0a31 in GitHub
Adding GetText Calls to JavaScript (JS) Code
Just like in PHP, make sure that all text in your JavaScript code can be translated into different languages.
WordPress provides the wp-i18n dependency to retrieve translations of text strings.
Specify a text domain for translations to be correctly matched and displayed based on the current language set in WordPress.
Commit Reference: See commit 7e73eaf in GitHub
To translate your code, you will need to generate POT files that include the original texts. You don’t need to create these files manually – below, you’ll find the WordPress commands you need to run to generate the POT files.
Here’s what the end result will look like:
While you can combine PHP and JavaScript strings into a single POT file, our demo maintains separate POT files.
Generating the POT File for PHP Strings
You need to run a Composer script that scans all the PHP files in your project, looks for GetText calls (which you previously added), and creates a .pot file that includes all the translatable strings in the project.
To do this:
- Add the Composer script
make-php-pot
to your project to avoid executing the full command manually each time you update the POT file.
Commit Reference: See commit 88a9323 in GitHub
- Run the make-pot command:
composer make-php-pot
Commit Reference: See commit c9767f1 in GitHub
Generating the POT File for JS Strings
Next, run a script that scans the JS files for GetText function calls and generates a .pot file with all the translatable strings it finds.
- Add the Composer script
make-js-pot
to create the JS POT file with the correct configuration.
Commit Reference: See commit e2da741 in GitHub
- Run the command:
composer make-js-pot
Commit Reference: See commit 2c31ed3 in GitHub
If your project includes bundled JavaScript scripts (for example, via Webpack), use @wordpress/babel-plugin-makepot instead.
You need to provide specific files to GetText for it to return translations. Here’s how the process works:
- First, you translate the content of your .pot files and save each translation in a .po file (Portable Object file) for each language. The .po file looks very similar to the .pot file but includes the translations.
- Next, from the .po file, generate an .mo file (Machine Object file), which is the machine-readable version of the translations.
- Place the .mo files in the folder where GetText expects them to be, typically under a directory like /languages in your plugin’s repository.
You can accomplish all of this using PTC (Private Translation Cloud) in just a few clicks.
Using PTC to Create Translations
PTC (Private Translation Cloud) is a software translation tool that provides high-quality automatic translations for .po, .mo, and .json files.
Free
Resource files translation
Available now
Completely free
Instant, high-quality automatic translations
Downloadable translated resource files
Paid
PTC Subscription
Coming soon…
Simple flat fee
Instant, high-quality automatic translations
Integrates with your Git repository and sends translations as merge requests
Unlimited translation rounds
Unlimited automatic translation, enhanced by AI and machine learning
Manage multiple projects
Create and manage your own glossary
Assign different user roles
To use Free resource files translation:
- Upload the resource files to PTC.
- Choose the target languages.
- Select the option to receive .mo files with compiled translations.
- Click the Translate button.
Once the automatic translation process finishes, download the translation files. Place the .po and .mo files into a specific folder in your plugin’s repository. In our example, we store the translation files in the languages/php folder.
PHP PO/MO File Commit Reference: See commit c1c17bf in GitHub
JS PO/MO File Commit Reference: See commit 7dc8463 in GitHub
Lastly, configure WordPress to recognize and load the translation files for both PHP and JavaScript components of the plugin or theme.
Load the Plugin’s Text Domain for PHP Files
Tell WordPress where it can find the translation files for your PHP code.
Commit Reference: See commit c36688c in GitHub
At this stage, the strings from the PHP file appear translated on the plugin’s admin page. We wrapped the Foo Banner string in a gettext function, but left it untranslated on purpose because it acts as a brand identifier.
Generate the JSON (JED) Translation File and Load Script Translations for JS Files
When translating JavaScript files in WordPress, you will use JED (JSON Extended Description) files. These JSON files are generated from MO files and contain the translations needed for your JavaScript scripts.
For optimal performance, WordPress loads JS translations only for the scripts currently in use. Each JSON translation file ends with a hash representing the relative path to the corresponding JS script, in order to accurately map the translations.
To generate and load JED files:
- Add the Composer script
make-js-json
.
Commit Reference: See commit 5cc9548 on GitHub
- Run the command
composer make-js-json
to convert the MO file into a JSON file for JS scripts.
Commit Reference: See commit f172167 on GitHub
- Load the script translations for your JavaScript files by telling WordPress where to find the JSON translation files. In our example, we use a file named
confirm.js
.
Commit Reference: See commit 49b3069 in GitHub
In our demo plugin, the strings from the JS file in the confirmation pop-up now appear translated.
Make Your WordPress Projects Multilingual
By translating your WordPress themes and plugins, you can reach a broader, global audience.
Whether your projects are free, premium, or custom, adding language support is a small effort that brings big rewards, allowing you to tap into a vast market of non-English speakers. WordPress itself supports numerous languages, and your themes and plugins should too.
Ready to make your projects more inclusive?