Making your project multilingual
Tools like Google Translate can automatically translate websites with reasonable quality. However, users will have a much better experience if you add support for multiple languages in your project and manage the translations yourself.
Making strings translatable in PHP
A good practice is to use one of the I18n (internationalization) functions for your hardcoded strings, even if your website starts with a single language. This way, you can add multilingual support more easily later.
If you've worked on a multilanguage-capable project, you most likely came across __()
and _e()
functions. The main difference between the __()
and _e()
is that __()
returns the value, while _e()
echoes it. Both functions take two arguments: the first one is the string to be translated, and the second one is the textdomain that identifies the translation file.
Textdomain is usually your project name written in kebab-case.
While WordPress functions like __()
and _e()
will definitely do the job, it is much better to use the variants of these functions that also escape the output. These are esc_html__()
and esc_html_e()
. There are also a few more functions for I18n you can use, but to keep it simple, we'll just mention these two for now.
Here is an example of using one of these functions:
<?php echo esc_html__('Contact', 'project-name'); ?>
Making strings translatable in JS
To translate the strings in the Block editor or options, you will first have to import the function from the @wordpress/i18n
library.
import { __ } from '@wordpress/i18n';
To output your string, simply use it like this:
{__('Icon position', 'project-name')}
Alternative functions you can use are:
_n
for singular/plural forms_nx
for singular/plural forms with gettext context_x
for a translated string with a gettext context
You can refer to the block editor handbook for more information on these functions.
The I18n class
The easiest way to add I18n support to a project created with Eightshift boilerplate is by using the WP-CLI command:
wp boilerplate create i18n
This command generated a new class inside the src/I18n
folder. This class instructs WordPress to look for translations in src/I18n/languages
with the textdomain defined as your project name. The next step is generating .po and .mo files that are used for translation.
Generating .pot file
You can create a .pot
(Portable object template) file by using WP-CLI. Run the following command in your project root:
wp i18n make-pot
Alternatively, you can use tools like Poedit to generate a .pot
file and generate translations from it later.
Translating with Poedit
Once you have the .pot
file, you can use Poedit to generate .po
and .mo
files that are used for translating hardcoded strings in your project. When generating the files, you can choose for which locale you're creating the translation for. For example, if you are creating a translation for the German language, your files should be named de_DE.po
and de_DE.mo
.
After generating the files, go to Translation -> Properties and navigate to the Sources Paths tab. Set the Base path to the theme folder path. In Excluded paths you can add folders like node_modules
, vendor
, and public
to exclude external packages.
In the Sources keywords tab you can set additional functions for use in your project for translations. Commonly used functions are:
_e
for translating a string and echoing it__
for returning a translated stringesc_html__
for returning a translated string which is escaped in a way it's safe to use within HTMLesc_html_e
for echoing a translated string which is escaped in a way it's safe to use within HTMLesc_attr__
for returning a translated string which is escaped in a way it's safe to use within an attributeesc_html_x
for returning a translated string which is escaped in a way it's safe to use within HTML, with a gettext context_n
for returning a translated string in a singular or plural form, based on the supplied number
If you're missing a string in your
.po
file be sure to check which function is used for translation for that string, and that the function is added to Sources keywords.
After updating the settings, click on Update from source code option to get the updated list of strings to translate.
The translation process is simple. The left column represents the source text, and the right column the translation. When you have finished translating the strings, copy the .po
and .mo
files to the src/I18n/languages
folder.
JS translations
The process of translating strings in JS has a couple of extra steps.
In order to translate strings in JS (e.g. Block editor strings), you will have to generate translation file. To do this, navigate to your src/I18n/languages
folder and use the following WP-CLI command:
wp i18n make-json <po-file> --no-purge
This will generate a .json
file for each JS file present. The strings are extracted from .po
files, so you'll already have the translations added. The --no-purge
flag is used to keep the existing translations in the .po
file.
The method used for setting the script translations is setScriptTranslations()
from the I18n
class.
The default way this works in Eightshift DevKit is that you need to have a single .json
file with all the JS translations. If needed, you can either modify this method to read from multiple files, or just merge all the .json
files into one.
If using the default setup (everything in one file) follow this naming structure: {textdomain}-{locale}-{handle}.json
.
For example, if your textdomain is project-name
and your locale is de_DE
, your file should be named project-name-de_DE-project-name-block-editor-scripts.json
.
The block-related translations depend on the language the user has set in WP admin.
Enabling languages and content translation
If the website itself needs to support content in multiple languages, a plugin is a good option.
The most common multi-language plugins are:
- WPML - one of the most popular plugins on the market. It is a paid plugin, but offers a lot of advanced options.
- Polylang - a free plugin (also has a paid Pro version).
Explore other options as well, you might find a plugin that is a better fit for your project than WPML or Polylang.
Most of the translation work will be done through the editor, since you'll need to translate the content on posts and pages.
Additional resources
Internationalization (I18n) and Localization (L10n) are very broad topics, so it's impossible to cover everything in a single blog post.
If you wish to know about the core I18n functionalities, or a bit more about how it is used in the Eightshift DevKit, here are a few resources which you may find interesting: