Note
Do You Even Need to Localize Your App?
How Localization Is Done in WordPress
A way to define a locale/language
A way to define text domains
A way to translate strings in your code
.pot files containing all of the words and phrases to be translated
.po files for each language containing the translations
.mo files for each language containing a compiled version of the .po translations
Defining Your Locale in WordPress
<?
php
// use the Spanish/Spain locale and language files.
define
(
'WPLANG'
,
'es_ES'
);
?>
Note
Text Domains
All code in WordPress core uses the text domain
default
.Paid Memberships Pro plugin uses the text domain
paid-memberships-pro
.Memberlite uses the text domain
memberlite
.
Setting the Text Domain
Note
load_plugin_textdomain( $domain, $abs_rel_path, $plugin_rel_path )
This function takes three parameters. The first is the
$domain
of your plugin or app (schoolpress
in our case). You then use either the second or third parameter to point to the languages folder from which the .mo file should be loaded. The$abs_rel_path
is deprecated, but still here for reverse-compatibility reasons. Just passFALSE
for this and use the$plugin_rel_path
parameter:<?
php
function
schoolpress_load_textdomain
(){
//load text domain from /plugins/schoolpress/languages/
load_plugin_textdomain
(
'schoolpress'
,
FALSE
,
dirname
(
plugin_basename
(
__FILE__
)
)
.
'/languages/'
);
}
add_action
(
'init'
,
'schoolpress_load_textdomain'
,
1
);
?>
This code loads the correct language file from our languages folder based on the
WPLANG
setting in wp-config.php. To get the path to the current file, we useplugin_basename(__FILE__)
, and thendirname(...)
to get to the path to the root plugin folder, since we are in the includes subfolder of our schoolpress plugin folder.
Note
load_theme_textdomain( $domain, $path )
If you have language files for your theme in particular, you can load them through the
load_theme_textdomain()
function like so:<?
php
function
schoolpress_load_textdomain
()
{
load_theme_textdomain
(
'schoolpress'
,
get_template_directory
()
.
'/languages/'
);
}
add_action
(
'init'
,
'schoolpress_load_textdomain'
,
1
);
?>
load_textdomain( $domain, $path )
This function can also be used to load the text domain, but you’ll need to get the locale setting yourself.
Calling
load_textdomain()
directly is not recommended for plugins or themes, but could be useful for projects in which you want to use a single domain across many different plugins. Callingload_textdomain()
directly also adds some flexibility if you want to allow others to easily replace or extend your language files. You can use code like the following to load any .mo file found in the global WordPress languages directory (usually wp-content/languages/) first, and then load the .mo file from your plugin’s local languages directory second. This allows developers to override your translations by adding their own .mo files to the global languages directory:<?
php
function
schoolpress_load_textdomain
()
{
// get the locale
$locale
=
apply_filters
(
'plugin_locale'
,
get_locale
(),
'schoolpress'
);
$mofile
=
'schoolpress-'
.
$locale
.
'.mo'
;
/*
Paths to local (plugin) and global (WP) language files.
Note: dirname(__FILE__) here changes if this code
is placed outside the base plugin file.
*/
$mofile_local
=
dirname
(
__FILE__
)
.
'/languages/'
.
$mofile
;
$mofile_global
=
WP_LANG_DIR
.
'/schoolpress/'
.
$mofile
;
// load global first
load_textdomain
(
'schoolpress'
,
$mofile_global
);
// load local second
load_textdomain
(
'schoolpress'
,
$mofile_local
);
}
add_action
(
'init'
,
'schoolpress_load_textdomain'
,
1
);
?>
This version gets the locale via the
get_locale()
function, applies theplugin_locale
filter, and then looks for a .mo file in both the global languages folder (typically /wp-content/languages/) and the languages folder of our plugin.
Prepping Your Strings with Translation Functions
__( $text, $domain = “default” )
Note
<?
php
// setting a variable to a string without localization
$title
=
'Assignments'
;
// setting a variable to a string with localization
$title
=
__
(
'Assignments'
,
'schoolpress'
);
?>
_e( $text, $domain = “default” )
<?
php
// echoing a var without localization
?>
<h2>
<?php
echo
$title
;
?>
</h2>
<?php
// echoing a var with localization
?>
<h2>
<?php
_e
(
$title
,
'schoolpress'
);
?>
</h2>
_x( $text, $context, $domain = “default” )
<?
php
$class_title_field_label
=
_x
(
'Title'
,
'class title'
,
'schoolpress'
);
$class_professor_title_field_label
=
_x
(
'Title'
,
'name prefix'
,
'schoolpress'
);
?>
<h3>Class Description</h3>
<label>
<?php
echo
$class_title_field_label
;
?>
</label>
<input type="text" name="title" value="" />
<h3>Professor</h3>
<label>
<?php
echo
$class_professor_title_field_label
;
?>
</label>
<input type="text" name="professor_title" value="" />
Note
_ex( $title, $context, $domain = “default” )
Escaping and Translating at the Same Time
esc_attr__()
esc_attr_e()
esc_attr_x()
esc_html__()
esc_html_e()
esc_html_x()
Creating and Loading Translation Files
#: schoolpress.php:108 #: schoolpress.php:188 #: pages/courses.php:10 msgid "School" msgstr ""
#: schoolpress.php:108 #: schoolpress.php:188 #: pages/courses.php:10 msgid "School" msgstr "Escuela"
Our File Structure for Localization
../plugins/schoolpress/schoolpress.php (includes localization.php)
../plugins/schoolpress/includes/localization.php (loads text domain and other localization functions)
../plugins/schoolpress/languages/schoolpress.pot (list of strings to translate)
../plugins/schoolpress/languages/schoolpress.po (default/English translations)
../plugins/schoolpress/languages/schoolpress.mo (compiled default/English translations)
../plugins/schoolpress/languages/schoolpress-es_ES.po (Spanish/Spain translations)
../plugins/schoolpress/languages/schoolpress-es_ES.mo (compiled Spanish/Spain translations)
Generating a .pot File
xgettext -o languages/schoolpress.pot \
--default-domain=schoolpress \
--language=PHP \
--keyword=_ \
--keyword=__ \
--keyword=_e \
--keyword=_ex \
--keyword=_x \
--keyword=_n \
--sort-by-file \
--copyright-holder="SchoolPress" \
--package-name=schoolpress \
--package-version=1.0 \
--msgid-bugs-address="This email address is being protected from spambots. You need JavaScript enabled to view it." \
--directory=. \
$(find . -name "*.php")
-o languages/schoolpress.pot
Defines where the output file will go.
--default-domain=schoolpress
Defines the text domain as
schoolpress
.--language=PHP
Tells xgettext that we are using PHP.
--keyword=…
Sets xgettext up to retrieve any string used within these functions. Be sure to include a similar parameter for any of the other translation functions (like
esc_attr__
) you might be using.--sort-by-file
Helps organize the output by file when possible.
--copyright-holder="SchoolPress"
Sets the copyright holder stated in the header of the .pot file. This should be whatever person or organization owns the copyright to the application, plugin, or theme being built.
Note
Translators are expected to transfer or disclaim the copyright for their translations, so that package maintainers can distribute them without legal risk. If [the copyright holder value] is empty, the output files are marked as being in the public domain; in this case, the translators are expected to disclaim their copyright, again so that package maintainers can distribute them without legal risk.
--package-name=schoolpress
Sets the package name stated in the header of the .pot file. This is typically the same as the domain.
--package-version=1.0
Sets the package version stated in the header of the .pot file. This should be updated with every release version of your app, plugin, or theme.
--msgid-bugs-address="This email address is being protected from spambots. You need JavaScript enabled to view it."
Sets the email stated in the header of the .pot file to use to report any bugs in the .pot file.
--directory=.
Tells xgettext to start scanning from the current directory.
$(find . -name "*.php")
This appears at the end, and is a Linux command to find all .php files under the current directory.
Creating a .po File
Creating a .mo File
GlotPress
Using GlotPress for Your WordPress.org Plugins and Themes
https://translate.wordpress.org/projects/wp-plugins<your-plugins-slug>/
https://translate.wordpress.org/projects/wp-themes<your-themes-slug>/
Creating Your Own GlotPress Server
Note
1 If not, locate and install the gettext package for your Linux distribution.