Skip Navigation

How to Internationalize, Localize, and Translate Your Themes and Plugins

Learn how to translate your WordPress themes and plugins and include these translations in your project.

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.

Message displayed by the demo plugin on the front-end

Users with access to the site’s backend also see:

An admin page to manage message status and content

A confirmation pop-up That Appears After saving changes

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)

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.

To run WP-CLI commands, install WP-CLI via Composer by running:

composer require --dev wp-cli/wp-cli-bundle

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.

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.

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:

An example of a POT file

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:

  1. Add the Composer script make-php-pot to your project to avoid executing the full command manually each time you update the POT file.
  1. Run the make-pot command: composer make-php-pot

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.

  1. Add the Composer script make-js-pot to create the JS POT file with the correct configuration.
  1. Run the command: composer make-js-pot

If your project includes bundled JavaScript scripts (for example, via Webpack), use @wordpress/babel-plugin-makepot instead. 

Create the Translations

You need to provide specific files to GetText for it to return translations. Here’s how the process works:

  1. 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.
  2. Next, from the .po file, generate an .mo file (Machine Object file), which is the machine-readable version of the translations.
  3. 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:

  1. Upload the resource files to PTC.
  2. Choose the target languages.
  3. Select the option to receive .mo files with compiled translations.
  4. Click the Translate button.
Creating the translations with PTC’s Free resource files translation tool

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

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. 

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.

Translated plugin strings on the admin page

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:

  1. Add the Composer script make-js-json.
  1. Run the command composer make-js-json to convert the MO file into a JSON file for JS scripts.
  1. 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.

In our demo plugin, the strings from the JS file in the confirmation pop-up now appear translated.

Translated confirmation pop-up

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?

Updated
November 25, 2024