Loading WordPress language files correctly

The 2017 guide for both developers and users.
wordpress language files

WordPress localization features allows you to make plugins and themes easily translatable through WordPress Language files (po/mo files).

This is true especially since WordPress 3.7 and it got a whole lot easier since WordPress 4.6.

A lot of improvement has been made to the whole translation system for WordPress, I felt it really needs a refreshed post.

WordPress language files – The confusion ( Developer edition )

For developers, it comes down to how to let WordPress know you have translation files the proper way.

As developers we were told to use “load_plugin_textdomain()” and point this to our language file in our plugin folder.

However in the past this would be the only place WordPress would look and if a customer added their own language file there, on the next update it would be gone!

There was an article on the web a while back promoting using a second call this time using the function “load_textdomain()” to point to a file in the WP language folder and that is what a lot of people did (including us).

This meant that users could place their language files in a predetermined place in the WP language folder and the translation would not be lost on the plugin update.

WordPress language files – The confusion ( User edition )

Users need to know where to put a custom translation for a plugin/theme, the problem is that in the past this could have been in several places.

The WP documentation tells developer to link to a folder inside their plugin folder called “languages” but the developer might use the folder “lang” and even then this will be lost when the plugin/theme is updated.

Some developers would add a second check again in a place of the developers choosing, but often in a custom named folder in the WP languages folder.

This meant there was no consistent way for a user to know where to place their custom translation files safely.

Loading language files the correct way (2017)

Since WP 4.6 this got a whole lot easier for both users and developers!

As a developer you now just have to make sure you are loading your language files correctly, following the WP documentation as below:

<br />
// for plugins<br />
add_action( 'init', 'myplugin_load_textdomain' );<br />
function myplugin_load_textdomain() {<br />
  load_plugin_textdomain( 'my-plugin', false, basename( dirname( __FILE__ ) ) . '/languages' );<br />
}<br />

<br />
// for themes<br />
add_action( 'after_setup_theme', 'my_theme_setup' );<br />
function my_theme_setup(){<br />
    load_theme_textdomain( 'my-theme', get_template_directory() . '/languages' );<br />
}<br />

Notice we fire these on the ‘init’ and ‘after_setup_theme’ hooks, this should mean everything will load nicely.

If you fire it directly or before their respective hooks you can have problems with some strings not translating and plugins to manipulate translations or to create multi lingual websites such as WPML, might not work at all.

As users we now have a convenient and consistently named place we can place our language files.

  • For plugins: /wp-content/languages/plugins/my-plugin-en_US.mo
  • For themes: /wp-content/languages/themes/my-theme-en_US.mo

The ‘my-plugin’ and ‘my-theme’ being the textdomain of the plugin/theme (usually found in the plugin readme.txt or the theme style.css at the top).

This is a great improvement over the old way and will prevent losing translation on updates in most cases.

In some cases the plugin/theme might already have a new translation in your languages stored on wp.org, if this is the case then it might overwrite your .mo file but in most cases this will be desired.

You can contribute to translations on wp.org if the plugin is hosted there, if it is a premium plugin there there is little chance it will be overwritten.

Bonus information

WordPress will try to find your WordPress language files in several places,for a plugin with a textdomain ‘my-plugin’ it would first look here:


If it does not find a translation there and the plugin specifies where to find one locally, it will look there:


If the plugin does no specify a path then WordPress will look here instead:


The WordPress documentation should be followed but in reality from WP 4.6 you don’t even have to specify a local file if you are not including any (if they are stored on the wp.org repo), so you could just add this:

<br />
// for plugins<br />
add_action( 'init', 'myplugin_load_textdomain' );<br />
function myplugin_load_textdomain() {<br />
  load_plugin_textdomain( 'my-plugin');<br />
}<br />
<br />
// for themes<br />
add_action( 'after_setup_theme', 'my_theme_setup' );<br />
function my_theme_setup(){<br />
    load_theme_textdomain( 'my-theme');<br />
}<br />

I hope this clears translations up a bit and if you have any questions or have anything to add please leave a comment below.

Unlock the Power of GeoDirectory!

Start your Online Business Now

Join Today!

Newsletter - Stay Updated!

Get the latest news, tips, and exclusive content directly in your inbox.

Published by Stiofan O'Connor

Stiofan O'Connor is the co-founder and CEO of AyeCode LTD. With his business partner Paolo, they are the makers of the GeoDirectory, UsersWP and Invoicing plugins for WordPress. He is a Full Stack developer specialized in WordPress development. Stiofan started building websites as a hobby in the early 2000s with PHP at first. He then moved to the CodeIgniter Web Framework for a while before discovering WordPress and ever since he never looked back. Today his WordPress themes and plugins are used with success by +100.000 active websites.