Intro.
Over 810 million websites are estimated to use WordPress (representing 40% of all websites on the Internet), and estimates suggest that Woocommerce powers over 5 millon active online stores.
For someone offering services related to those technologies (currently through Fiverr ➡️ Profile here) sounds like a nice client base. Everyones goto platform is Wordpress related, which also leads to many misuses and pitiful configurations (to not talk about performance!)
So after being confronted to every kind of confussions from clients asking for my services at Fiverr, I decided to create the simplest, minimal guide possible, to explain how Wordpress Translations work (and how they don't), taking some of those confussions as a starting point.
The identity of the aforementioned will remain anonymous 😜 But first, let's understand how Wordpress translations actually work.
How does Wordpress translations actually work?
Here we will cover the basics of Wordpress translations, from the practical to the theorical, convering:
- What are pot, po and mo files?
- Loading translations
- Wordpress translation functions
1. What are pot, po and mo files?
Wordpress (and all of its plugins like Woocommerce or Budypress) use the GNU gettext internationalization (i18n) and localization (l10n) system for writing multi-lingual programs.
The file extensions used by this system are: .POT (Portable Object Template), .PO (Portable Object) and .MO (Machine Object) files, more here at Wikipedia.
The idea behind using a system like this is to separate programming from translating, so themes, child themes and plugins can be easily translated into other languages by specialist with no undestanding of coding.
- POT files (
.pot
): The first step for the internationalization of our theme or plugin is to create our.pot
file. This file will have no translations of its own, but it will be the template for all localization files to come. These files are often created by the developer and make available in the./languages
folder of a theme or plugin.
Awp-cli
command line tool command can be run to scan the theme or plugin for available internationalization strings. WP-cli is a command-line interface for Wordpress.
It is worth mentioning that the theme must be developed with this in mind, using Wordpress internationalization functions (more in the next section). On the contrary our resulting.pot
file will have no translatable strings or texts.
Many times, a client comes asking for me to translate a theme that it was not created with this capability. In such cases it is mandatory to do some development work in order to make the required texts translatable. It is sometimes hard to make the client understand that this not a translation work, but a development shenanigan.
Also in these cases it is better to contact the original developer itself first, and ask for an internationalization-ready theme or plugin, in order to avoid conflicting versions. Other times this can be partially solved with the development of child theme.
In case its all good with our code, we can run the followingwp-cli
command, and create our.pot
file.
wp i18n make-pot ~/Wordpress/wp-content/themes/my-theme/
PO files (
.po
): A translator will take the.pot
template file and translate the strings using a software like Poedit or GlotPress (web-based). The translator will choose the target locale, translate all or some of the strings and a.po
file will be created.
In case a plugin or a themes continues its development cycle and more translations are added, a new.pot
file will be generated by the developer, and the initial.po
translation can be updated with the new strings, to be in turn, also translated.
Sometimes.po
files are only partially translated, resulting in partial texts translations in the front-end of the site. This can be easily checked opening the.po
file being loaded and searching for the un-translated string detected in the site.
It is often the case that some of this strings were not correctly created by the developer. Which require, in many cases, some nasty hacks to solve.MO files (
.mo
): From a.po
file, all nice and ready with all (or some) translations a.mo
binary file is compiled by the software. This file contains all the original strings and their translations, in a format ready for fast extraction. These are the real translations files used by the Wordpress software and all its plugins.
2. Loading Translations
/*
* Theme Name: My Theme
* Author: Theme Author
* Text Domain: my-theme
*/
A key concept when loading Wordpress translations is the "text domain" of our theme or plugin.
The "Text Domain" is a unique identifier that WordPress will use to load the necessary translation specific files to our theme, child theme or plugin. Specifically our .mo
files.
The Text Domain is defined in the header of our style.css file. It must be in lower case, without spaces and if necessary we must use hyphens instead of underscores.
The next step is to check where our translation files are being searched for. The standard for themes and plugins is to configure these files to be loaded in a “languages” folder, located in the root directory of our WordPress theme, child theme or plugin.
The special function load_theme_textdomain
is used in order to specify this.
function mytheme_setup{
load_theme_textdomain( 'my-theme', get_template_directory() . '/languages' );
}
Then that setup can be attached to
The .mo files must be named based on the locale exactly. Meaning that /languages/
folder, inside a theme or plugin root, a Brazilian Portuguese translation file should be pt_BR.mo
and pt_BR.po
.
Now, many non-experienced Wordpress users that want to modify a plugin or theme translations, usually grabs that same .po
file, edit with PoEdit and save the changes. This normally results in modifications being overriden once the plugin or theme is updated.
How to solve this?
Wordpress will check for other directories for each theme or plugin translation files. So, in case you need to modify a translation (or create one using the .pot
files provided by the developer), the resulting files must be placed in other directory, specifically at the wp-content/languages/
folder.
If translation are for a theme you should place your files at wp-content/languages/themes/
and wp-content/languages/plugins
well, for plugins. A special consideration should be taken in relation to the file names.
So for example, if our theme has a text-domain of twentytwentyfour
, then our Brazilian Portuguese translation files should be named twentytwentyfour-pt_BR.mo
and .po
respectively. If the configured locale for our Wordpress instance is pt_BR
then translations will be loaded from that file, which takes priority.
This is very important, and often a cause of confussions on whay translations are not loading correctly.
To configure our locale for our Wordpress instance we must go to Configurations > General
or setup a WPLANG
constant in our wp-config.php
file.
3. Wordpress translation functions
Translations functions should be used on any Wordpress theme or plugin that is supposed to be "translatable" or in more technical terms, on any theme or plugin that what to be internationalized (and later localized).
Without using these functions in your themes or plugins texts (aka. strings) will be "hard-coded", non-"translatable", fixed: subsequently they won't be detected by the software scanning the code when creating the corresponding .pot
file, and you'ill end up with translations problems.
This is why if you have no coding skills, should always use professional themes and plugins. Or you can reach out to me asking for help, and I will be more than glad to help indeed, but at the same time pissed of with the lazy developer that created the problem in the first place.
So, here are the most common translations functions that should be used in any internationalized Wordpress theme or plugin. There many non-obvious ones, but for those more in-depth matters you can Otto's great article about More Internationalization Fun. Withour further addo:
- __(): Retrieves the translation for the first argument.
- _e(): Displays the translated text.
- _x(): Retrieves translated string with gettext context.
- _ex(): Displays the above.
- _n(): Translates and retrieves the singular or plural based on the number supplied.
If you are not a developer just keep in mind that your theme or plugin should be developed using this functions in order to have internationalization and localization capabilities.
Let's follow with a summary of the misconceptions and errors detected when takling to clients.
Common confusions around i18n and l10n
Confussion #1
Themes and child themes
Basically i want to keep the parent them in English and have a Portuguese translation in the child theme therefore the website will have two languages
Child themes are there to extend parent themes functionality, but they work in the same locale context. In order to get the site in two languages within a Wordpress structure, you can use a Multi-site installation and keep different structures under the same install, or use a multilingual plugin like WPML (paid) or Polylang (free, paid).
Confussion #2.
Overriding files
Another common problem is when "translations disappear".
As stated before the right way to (somewhat) persistently modify a translation for a theme or plugin that has been correctly created using translation functions, is to upload files, with the correct filename (considering text-domains) in the wp-content/languages/{plugins|themes}
folder. Else all translations will be replaced when the theme or plugin is updated and new original .po
, .mo
and hopefully .pot
files are downloaded.
Confussion #3.
Files are named and placed ok, but still no translations?
Check the Sites language locale configured at Configurations > General
or via the WPLANG
constant.
In order for Wordpress, Woocommerce or any other plugin to pick the right translation files, not only the filename must have the correct locale but they must match the configured (and active) locale for the site.
For example, for the woocommerce-pt_BR.mo
translation file to be loaded, then the site configured locale must be pt_BR
, else your nice and tidy translations won't load 🤷
Confussion #4.
Can't find some texts to be translated in my .po
or .pot
file.
In Wordpress not all translations are handled by the theme. Each plugin has its own translations files. Many plugins participate in some form of front-end screen rendering, so their translations files must also be translated.
Other texts are not part of translation files but part of the content itself. Maybe some Elementor Block? In this cases we must detect and change the text from each individual content piece (article or block), using the Elementor interface.
Confussion #5.
Admin Dashboard not translated.
When more or one translation is present and configured, admins (and most registered users) can choose their locale in their logged-in user profile. This can thus be different from the anonymous user front-end locale. So make sure which locale is configured for your user at {your_site}/wp-admin/profile.php
url once logged-in.
Final thoughts
Wordpress i18n and l10n can be confusing at first contact, but it is a well tested and efficient system wich goes back to 1995 with the release of the GNU gettext, free software implementation.
In case you need any help with your Wordpress or Woocommerce translations, and before installing Loco Translate and start messing around with translation files, drop me a message at Fiverr and allow me to assist or at least guide you out of your translation problems.
It will be my pleasure to detect and fix any translation problem you might be having!
That said, Mālama pono, legyen szép napja, tenha um ótimo dia, and have a great day 😻!