How to Internationalize and Translate WordPress Themes and Plugins
WordPress internationalization (i18n) ensures your themes and plugins are translation-ready. PTC then translates your theme or plugin with AI-powered accuracy.
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
Each step of this tutorial is demonstrated with code changes. Check the demo plugin’s repository to review them via Git commits.
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:
Our goal is to make all strings translatable and add Spanish translations. This way, users who switch WordPress to Spanish can use the plugin in their language.
Steps to WordPress Plugin Internationalization (i18n) and Localization (l10n)
1. Initialize Composer and Install WP-CLI as a Dev Dependency
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
2. Wrap All Texts in GetText Calls
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
3. Generate the Portable Object Template (POT) Files
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.
4. Create the Translations
You need to provide specific files to GetText for it to return translations. Here’s a general overview of the process:
- First, translate the content of your .pot files and save each translation in a .po file (Portable Object file).
- 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 don’t have to complete the steps above manually. PTC (Private Translation Cloud) can do it for you 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.
To get started:
- Set up up your project in PTC and link it to your repository. PTC will automatically detect your resource files.
- Choose the target languages.
- Wait for PTC to generate AI-powered translations, delivered directly to your repository as a merge request.
The translation files will be stored in a specific folder in your plugin’s repository. In our example, the translation files are 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
5. Configure and Load Translation Files in WordPress
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
The PHP strings show as translated on the admin page. We left the “Foo Banner” string untranslated as it’s a brand.
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. WordPress itself supports numerous languages, and your themes and plugins should too.
With PTC, you get…
Instant, Better Than Human Translations
Integratation with your software repository and translations sent as merge requests
Unlimited translation rounds, enhanced by AI and machine learning
Continuous localization for WordPress themes and plugins
Developer Guides
How to Internationalize and Translate WordPress Themes and Plugins