You may ask yourself what is so special about this post. Does not the codex cover load_plugin_textdomain()
and load_theme_textdomain()
but this posts will show what else you can do with it.
With this code for the theme and plugin you can add the translations in different places. The two reasons for this are:
- This allows for the translation to be placed in multiple places when the theme/plugin author does not add the translations to the theme/plugin and not have them deleted in every update.
- This also allows for the translations to be edited without needing to maintain the whole translation. For example there might be only one string that needs to be different for a site and so can be added to language directory before the theme/plugin language directory.
How do .mo files work?
So with the translation in the mo files if two of the same translations are loaded only the first translation will be displayed. So that is why in these code examples the plugin/theme language folders are loaded last. With if you only need to change a single string you would only need to add a single translation string in the directory that is loaded before.
For the theme there are three different places; the WordPress language directory, the child theme language directory and the parent theme language directory.
<?php | |
function theme_name_setup(){ | |
$domain = 'theme-name'; | |
// wp-content/languages/theme-name/de_DE.mo | |
load_theme_textdomain( $domain, trailingslashit( WP_LANG_DIR ) . $domain ); | |
// wp-content/themes/child-theme-name/languages/de_DE.mo | |
load_theme_textdomain( $domain, get_stylesheet_directory() . '/languages' ); | |
// wp-content/themes/theme-name/languages/de_DE.mo | |
load_theme_textdomain( $domain, get_template_directory() . '/languages' ); | |
} | |
add_action( 'after_setup_theme', 'theme_name_setup' ); |
For the plugin there are two different places; the WordPress language directory and the plugin language directory.
<?php | |
function plugin_name_load_plugin_textdomain() { | |
$domain = 'plugin-name'; | |
$locale = apply_filters( 'plugin_locale', get_locale(), $domain ); | |
// wp-content/languages/plugin-name/plugin-name-de_DE.mo | |
load_textdomain( $domain, trailingslashit( WP_LANG_DIR ) . $domain . '/' . $domain . '-' . $locale . '.mo' ); | |
// wp-content/plugins/plugin-name/languages/plugin-name-de_DE.mo | |
load_plugin_textdomain( $domain, FALSE, basename( dirname( __FILE__ ) ) . '/languages/' ); | |
} | |
add_action( 'init', 'plugin_name_load_plugin_textdomain' ); |
WordPress language directory
The WordPress language directory can be found in wp-content. The code that we used would mean we would need a plugin or theme directory in the language directory for the translations.
wp-content
– languages
– – plugin-name
– – – plugin-name-de_DE.po
– – – plugin-name-de_DE.mo
– – theme-name
– – – theme-name-de_DE.po
– – – theme-name-de_DE.mo
WordPress 3.7
With the changes in WordPress 3.7 it will add support for automatically installing the right language files and keeping them up to date. These translations will be stored in the WordPress language directory under one directory for themes and another for plugins. The standard directory structure will look like this.
wp-content
– languages
– – plugins
– – – plugin-name-de_DE.po
– – – plugin-name-de_DE.mo
– – themes
– – – theme-name-de_DE.po
– – – theme-name-de_DE.mo
You might ask yourself how this code will work with WordPress 3.7. What ever you are doing in now to load the text domain will work fine in WordPress 3.7. As the code uses the WordPress language directory but not the themes or plugins directory in the WordPress language directory all will be fine.
WordPress checks if there are translation is in plugin/theme and if not then it will load the translation from WordPress language directory. If the translation are in the custom location in the WordPress language directory then the translations will be merged but the translations from the custom location will used unless not defined.
In the future plugin and themes on WordPress.org repository will be able to update translations separately to the plugin or theme updates(This will launched separately to WordPress 3.7).
Otto has a great post on this that must be checked out.
Here is how you could conditionally load only one translation file and all of them one after each other.
<?php | |
function theme_name_setup(){ | |
$domain = 'theme-name'; | |
if ( $loaded = load_theme_textdomain( $domain, trailingslashit( WP_LANG_DIR ) . $domain ) ) { | |
return $loaded; | |
} elseif ( $loaded = load_theme_textdomain( $domain, get_stylesheet_directory() . '/languages' ) { | |
return $loaded; | |
} else { | |
load_theme_textdomain( $domain, get_template_directory() . '/languages' ); | |
} | |
} | |
add_action( 'after_setup_theme', 'theme_name_setup' ); |
<?php | |
function plugin_name_load_plugin_textdomain() { | |
$domain = 'plugin-name'; | |
$locale = apply_filters( 'plugin_locale', get_locale(), $domain ); | |
if ( $loaded = load_textdomain( $domain, trailingslashit( WP_LANG_DIR ) . $domain . '/' . $domain . '-' . $locale . '.mo' ) ) { | |
return $loaded; | |
} else { | |
load_plugin_textdomain( $domain, FALSE, basename( dirname( __FILE__ ) ) . '/languages/' ); | |
} | |
} | |
add_action( 'init', 'plugin_name_load_plugin_textdomain' ); |
Great post, just wondering, you’re not using the new WP 3.7 load_plugin_textdomain( ‘plugin-slug’ ); or the load_theme_textdomain( ‘theme-slug’ );? and as those 2 functions use a fallback to check the plugin/theme languages folder in case, are your gist still useful?
load_plugin_domain is not a new function for WordPress 3.7. If you continue to use my gist the translation will be loaded from the plugin (currently there is no other way to update translations) and if there is no translation WordPress looks in the language folder of WordPress. I hope that makes sense?