Hi @james!
Iāll try to give a detailed answer (maybe someone could use it as a kinda draft for a tutorial).
I assume that:
- plugin source files are properly localized, translatable strings are wrapped with _(), e(), esc_html() or esc_html_e().
- plugin uses a single text-domain (see notes in the Issues section).
How to create and update the .pot file for a plugin
There are two typical ways to generate a .pot
file from the source code.
-
Paid and lazy is Poedit PRO, which has a special option āTranslate Wordpress theme or plug-inā. It parses the code files and extracts localized strings (GNU gettext, twig templates) into a .pot
automatically. Any version of the Poedit (even free) (re)creates .po
and .mo
files when saving a translation and can update strings from the source/pot files.
-
Free and flexible is making a .pot file directly from the command line which requires WP-CLI or gettext utilities (see below). Typically I switch to a plugin folder and run:
wp i18n make-pot . languages/text-domain.pot --domain="text-domain"
.
This looks for localized strings in a current directory and its subdirectories, checks if they belong to the common text domain and puts them into a valid .pot file in languages
directory. Assuming text-domain
is a proper value of the āText Domainā in a plugin meta and is used in all localized strings. The make-pot
utility is documented here. It also extracts some plugin meta (author, version, link, description etc.) and includes into translation files. Those strings can be translated, too. They are shown in plugins list etc.
The simplest way to update the .pot
file is usually to recreate it. This guarantees that there are no lost or outdated strings from previous builds.
Iāve used Poedior Pro version some time ago for that, but now I opt out in favor of Free version + command line tools.
Preferred solution for translating into .po and .mo files
This depends on a project type and environment.
-
GlotPress native interface is used for projects hosted on translate.wordpress.org and similar.
This is probably the best tool ever for collaborative translation within WP ecosystem. Itās deeply integrated with plugin/theme directories (which allows authors to request translations for meta data - readme files etc.), supports user roles and many other things. And all the updates are delivered to the end users automatically through the WP upgrade system.
I havenāt configured Glotpress serverside yet myself, but if I understand it right, Glotpress manages the local packages and rebuilds .po and .mo when a certain % of strings gets translated (approved). This triggers the update system, all users get a notification āNew translation for %plugin_name% is availableā in their dashboards.
But there is also the reverse side of the coin. All strings should be approved by PTE (Project Translation Editor) or global editors. And if your project has no editor for your locale, all translated strings can hang in āWaitingā status for years.
The good news is that anyone can request PTE status for a certain project. Personally, Iām now building relations with local WP Team and its Locale Manager. Which means I ask for PTE rights in Slack and (probably) get it in some days. This allows to approve strings and release translations immediately (if > 95% of strings are ready). BTW, I openly declare that Iām a member of ClassicPress community and this doesnāt make any harm.
-
Poedit
The most well-known tool and my favorite. I use Free version now, but it covers almost all my needs.
Features:
- Automatically (re)builds .po and .mo on save
- Highlights links, expressions.
- Has a simple build-in validator, which often helps avoid loosing expressions, whitespaces and punctuation marks at the beginning/end of lines.
- Allows to update the list of strings form .pot files (even in free version)
- Supports comments (/* translators: ā¦ */) and suggestions.
To my mind this is the most suitable tool for a non-techie translator, who works with autonomous files. Itās simple and handy. Pro version allows to do the whole job with no technical knowledge at all.
-
Poedit-alike alternatives (GUI)
Plenty of them. Probably the most similar free analog for Win is Virtaal. Itās a bit less functional, but quite simple and free. *nix have their own tools. Iāve tried gTranslator for Windows, but it crashed when loading huge .pots several times and I deleted it. Anyway, all those tools are very similar and to be honest I donāt see any meaningful difference. They all can do the job.
An interesting alternative is POEditor.com. Unlike others, this tool is a web-based online service. Itās very similar to poedit-alike tools but also implements some advantages of Glotpress (collaboration, user roles). Iāve tested it on a free plan for several hours and it seemed nice. Free version has a limit of 1000 strings. (But they also offer a free plan for open source projects by direct request). I still prefer Poedit for local projects because local sowtware is a bit faster in use (less clicks/ajax loads).
-
Hardcore
Certainly, any .pot
can be also translated using pure notepad or other text editor (technically .pot is a structured plaintext file and .po is just its advanced copy). But this is not really useful, when there are hundreds of strings to translate.
Updating .po and .mo
This is a built-in feature for almost any GUI tool (Poedit, Virtaal and others). They all have an option kinda āUpdate strings from .pot/templateā, which merges existing .po
file with a new .pot
. And .mo
files are regenerated on save.
But for techies there is a āhardcoreā method to do this from the command line. It requires gettext tools (here are compiled versions for Windows).
To merge existing .po
file with a new .pot
:
$ msgmerge my-existing-locale.po new.pot
and then to produce a relevant .mo
file:
$ msgfmt my-existing-locale.po
(Full docs are here)
What needs to be done in order to get the translations to show up in the admin interface
-
If a plugin/theme uses translate.wordpress.org, all translations are loaded automatically after being approved. To get an update user has to go to the Dashboard and click āUpdate translationsā there. (Assuming his site uses a relevant locale).
-
If a plugin/theme is installed manually, localized files (.po and .mo) should be placed under wp-content/languages/plugins/
(or .../themes/
).
Filename format: {text-domain}-{locale}.{ext}
, where {locale}
is kinda āru_RUā and {ext}
is po
or mo
. E.g. russian localization files for text-domain āclassicpressā would be classicpress-ru_RU.po
and classicpress-ru_RU.mo
.
Typical issues and difficulties
(to help developers to improve the localization of their products).
-
Inconsistent strings in similar parts of the plugin.
-
Insufficient space. English strings are usually shorter than their translations. This is sometimes critical when translating UI elements.
-
Partial localization. Top losties are
value
attributes for buttons and inputs, labels. The worst (and common) situation is when localized parts (hints, descriptions etc.) mention names of UI elements which are not yet localized. Or vice versa. This is a potential threat. E.g. you have a readable button āDo it!ā but a related warning āThis button will delete all your dataā is in another language and unreadable for users
-
One-word strings for different types of speech. E.g. when āPostā is both verb and noun. In English both strings have exactly the same spelling, but in Russian (and other languages as well) they should be translated separately (2 different words: āŠŠ°ŠæŠøŃŃā Šø āŠŠæŃŠ±Š»ŠøŠŗŠ¾Š²Š°ŃŃā). But since the English string is also the unique id (
msgid
) in the .pot file, there is no way to translate both cases separately. All occurrences are merged into a single line.
-
Multiple text domains in a single plugin. WP automatitially loads only one text-domain per plugin. But developers often create a ābrandedā menu page which unites several products. This page doesnāt belong to a certain plugin and devs sometimes use a different text domain for it. In this case English version looks ok and our tools even successfully include all strings into a .pot file. But WP doesnāt load the second text-domain by default. This leads to a ālanguage mixā when ābrandā pages (or some parts of the output) are still shown in English (even when all strings are actually translated!). To fix it, plugin should probably make a separate
.pot
(e.g. my-brand-text-domain.pot
), then build separate translation files (e.g. my-brand-text-domain-ru_RU.mo
and my-brand-text-domain-ru_RU.mo
) for each supported locale and then place them under wp-content/languages/plugins/
or use load_text_domain()
functions. I didnāt tested any fixes yet, but logically it should work.
-
Hardcoded local links. E.g. āen.wordpress.orgā instead of āru.wordpress.orgā.
-
Javascript / ajax data. This is a real problem, because .pot files are used to localize PHP/html files only. But a huge part of content is dynamic now (messages, notification, elem lists). Some strings are often hardcoded into JS. However, WP 5.0 introduced JavaScript i18n support (similar way:
wp i18 make-json ...
). I havenāt used this yet.
Translatorās guides and tools
By the way, talking about Russian language in particular, I recommend using Yandex.Translate. Being the native russian search engine and one of the most famous russian IT-companies, they have very strong algorythms for this language. Yandex translates is much more accurate in EN->RU direction than Google. I guess, there are similar native translation services for other worldwide languages.