Main menu

Ensuring WordPress loads your translation files

If you're having trouble displaying translated strings on your site, it's possible that WordPress is not finding the file that holds your translations. This guide should help you find out if your translation files are being read and how to fix it if they aren't.

This is a general information article about WordPress localization. It's not specific to using Loco or any other translation software.

Brief introduction to Gettext

Gettext is the localization system that WordPress uses to load translations. To be more specific: WordPress reads the Gettext MO file format. Loading these files is all WordPress needs to do. It's up to you to ensure they're valid and in the right place.

You don't need any special software or any PHP extensions to simply load translations into WordPress. Generating MO files is a different story, but for now we'll assume you've already got a file and just want to see it working on your site.

You might notice that MO files are often accompanied by PO files with the same name. These are the human-friendly source files from which the binary MO format is compiled. WordPress does not read PO files. For the rest of this guide we're only interested in MO files.

Gettext uses the concept of text domains, and so does WordPress. A text domain is simply a namespace that keeps your translations separate from other people's. Don't confuse this with the Internet domain of your site. It's just a simple label and we'll discuss it more in a moment.

Check your language code is correct

If you've downloaded a theme or plugin that contains MO files, only one step should be necessary to see the translations on your site: Just set your WordPress language. However, if the MO file you want to load isn't named according to the exact code of your language setting, you won't see any translations.

For example, if your site is set to Brazilian Portuguese, your MO file must be named "myplugin-pt_BR.mo" because the language code is "pt_BR", not "pt" or "BR" or even "pt-BR". It must match exactly. Likewise if the file is named "myplugin-el.mo" (language code without a region) you must use just "el".

If you don't know what your language code is, or don't know exactly which form to use, check the official list and use the code in the "WP Locale" column.

Check your MO files are in the right place

If you've downloaded a theme or plugin, its MO files should already be in the right place. However, some understanding of how WordPress loads these files will be useful if you're doing your own thing, or if you're having trouble.

Languages files are likely to be found in two common locations, (1) inside the theme or plugin as the author supplied them, and (2) in the global languages directory when installed by WordPress. Themes and plugins can define alternative locations, but we'll only cover the WordPress standards here.

Global languages directory

The global languages directory (WP_LANG_DIR) is used by WordPress to install language files independently of themes and plugins. This makes files installed here safe from theme and plugin updates (although - be warned - not from translation updates).

Unless you've configured WordPress differently, your global languages directory will be at "wp-content/languages" with two possible sub-folders for themes and plugins. If you don't see these folders, you can just create them when you need them.

Theme MO locations

Themes load translations by calling the load_theme_textdomain function. For example the Twenty Fourteen theme has the following line in its functions.php file

load_theme_textdomain( 'twentyfourteen', get_template_directory().'/languages' );

This tells WordPress to look in the theme's languages folder for a MO file named "{locale}.mo" where {locale} is the exact code WordPress will obtain from your current settings.

If WordPress fails to find a MO file at this exact location, it will then look in the global languages directory. Under this location the file must be named "themes/{domain}-{locale}.mo" where {domain} is the text domain "twentyfourteen" in the example above.

So in short, WordPress will look in only two places for a theme's MO file:

  • {absolute_path}/{locale}.mo
  • wp-content/languages/themes/{domain}-{locale}.mo

e.g. for twentyfourteen's French translations:

  • wp-content/themes/twentyfourteen/languages/fr_FR.mo
  • wp-content/languages/themes/twentyfourteen-fr_FR.mo

Note that {absolute_path} is the full path given to the load_theme_textdomain function. If the theme author has left out this parameter it will default to the theme's top-level directory.

Plugin MO locations

Just to keep it interesting, plugins load translations slightly differently. They call the load_plugin_textdomain function which (unlike themes) requires that the MO file is always named "{domain}-{locale}.mo" in full. It also takes a relative path from the plugins directory to target the language files.

Similarly to above, the only two places WordPress will look for a plugin's MO file are:

  • wp-content/plugins/{relative_path}/{domain}-{locale}.mo
  • wp-content/languages/plugins/{domain}-{locale}.mo

e.g. for "myplugin's" French translations:

  • wp-content/plugins/myplugin/languages/myplugin-fr_FR.mo
  • wp-content/languages/plugins/myplugin-fr_FR.mo

To highlight some key differences between plugins and themes:

Translations inside a theme's folder must not include the text domain in the file name. This is the one special case. Plugin translations and any translations under the global languages directory must include the text domain.

Themes pass an absolute path to load_theme_textdomain, whereas plugins pass a relative path to load_plugin_textdomain.

Use the right Text Domain

You'll notice that above we simply used the folder name of the plugin and theme as their text domains. It's good practice to do this, but it isn't required. More importantly, you can't just assume that plugin and theme authors have done it this way. If your translations are not showing up and you're sure the files are in the right place, this is a good thing to check.

Checking for the right text domain might not be easy, and it will involve looking at the author's code. If you're lucky the author will have added a file header specifying the text domain. For a theme, open up style.css and look for something like this at the top of the file:

/*
Theme Name: Some Theme
Text Domain: somedomain
*/

Similarly a plugin can include this header in its main PHP file.

Authors don't always include this header, so if you're still hunting for the right text domain you'll have to look more closely at the code. Try searching for a function call that actually prints translated text. The most common function is the __ (double underscore) function. Here's an example:

echo __( 'Hello', 'somedomain' );

This function call gives away that "somedomain" is the text domain that you need WordPress to load. If the function calls don't include a text domain, then WordPress will look for "default" and translations will be mixed in with WordPress's core translations.

Watch out for filters

WordPress filters can alter the MO file loading process at various stages. If you know you're doing everything correctly and WordPress still won't load your file, then its possible that another plugin is altering something. The best way to eliminate this problem is to disable every plugin, except the one you're translating.

Debug it

If you still can't see your translations then you're going to have to get your hands dirty to find out whether WordPress is trying to load your MO file at all.

If you're happy writing some code, the best thing to do is identify what MO file paths WordPress is actually trying. The load_textdomain action is a good candidate for seeing what WordPress is doing:

function debug_load_textdomain( $domain , $mofile  ){
    echo "Trying ",$domain," at ",$mofile,"<br />\n";
}
add_action('load_textdomain','debug_load_textdomain');

This code will print every attempted MO file load onto the screen. If yours is amongst them, check the file path and make sure your MO file is saved at that location. If you don't see your text domain amongst the output then it's likely the plugin or theme isn't set up correctly.

Note that the add_action code must run before your themes and plugins start loading text domains. Try putting this code in your themes's functions.php file to start with. If you can't get it to work then a "must use" plugin is another good option.

Summary

If your translations don't show up, check each of these possible problems:

  • Check the MO file is valid;
  • Check your current language setting;
  • Check the name and location of your MO files;
  • Check you know the correct Text Domain;
  • Disable other plugins that might be interfering;
  • Debug the MO loader to see what WordPress is trying to load;
  • Finally - contact the theme/plugin author if you suspect it's not localized properly.