How to Make Multilingual Plugins and Themes
John P Bloch ● 2016-02-20 ● WordCamp Miami
About MeJohn P Bloch
Lead Web Engineer at 10up10up is hiringTell them I sent youSeriously, we’re always hiring
Assumptions& Definitions
Assumptions
• You can write PHP• You are writing plugins or themes for distribution on the
wordpress.org repositories
Definitions
Internationalization
The process of making your code translatable at all.
Abbreviated as i18n
Localization
The process of using translated text in internationalized code.
Abbreviated as l10n
Definitions
Internationalization
The process of making your code translatable at all.
Abbreviated as i18n
Localization
The process of using translated text in internationalized code.
Abbreviated as l10n
Why should you care?
Why should you care?
• Empathy• More than half of all new WordPress installations are in languages
other than English
Why should you care?
• Empathy• Grow your potential user-base• Potentially make more money• Make more of an impact in the world
How to Internationalize Code
Text Domains
A text domain is a namespace for your code’s translations
Text domains need to be unique within plugins or themes
Use your plugin or theme slug
Text Domains – Loading Themes
load_theme_textdomain( $textdomain, $path // where your translations are)
Run on after_setup_theme action$path needs to be an absolute path
load_plugin_textdomain( $textdomain, false, // deprecated $path // where translation files are)
Run on plugins_loaded action$path is relative to wp-content/plugins
Text Domains – Loading Plugins
Plugin and Theme Headers
Plugins and themes have two special headers:
Text DomainDomain Path
Basic Translation Functions
__( $text, $textdomain )_e( $text, $textdomain )_n( $singular, $plural, $count, $textdomain)
Basic Translation Functions
$draft_count = get_my_drafts_count();printf( _n( 'I have one draft.', 'I have %s drafts.', $draft_count, 'my-textdomain'), $draft_count );
Basic Translation Functions
$draft_count = get_my_drafts_count();if( 1 === $draft_count ) { _e( 'I have one post.', 'my-textdomain' );} else { printf( __( 'I have %s drafts.', 'my-textdomain' ), $draft_count );}
Basic Translation Functions
_x( $text, $context, $textdomain )_ex( $text, $context, $textdomain )_nx( $singular, $plural, $count, $context, $textdomain)
Basic Translation Functions
You can also leave longer comments for the translators
printf( /* translators: The placeholder is the current user’s first name */ __( 'Hello, %s!', 'my-textdomain' ), $current_user->first_name);
Advanced Translation Functions
number_format_i18n( $number, $decimals = 0)
1234567.891,234,567.891.234.567,89
Advanced Translation Functions
date_i18n( $format, $timestamp = false, $gmt = false)
'F j Y''February 20 2016''Febbraio 20 2016'
Advanced Translation FunctionsHomework
Look up these translation functions:
wp_localize_script()esc_html__()esc_html_e()esc_html_x()
esc_attr__()esc_attr_e()esc_attr_x()
Final Steps
Final Steps
• Generate .pot file• Official repositories provide web tools
• Publish .pot file• Usually packaged with plugin or theme in the languages directory
• Add translation files to your plugin or theme• Or don’t. Plugins have language packs now.
Gotchas
Gotchas
• Line breaks• Empty strings• Formatted strings vs. interpolation
_e( "You live in $state", 'my-plugin' );
#: my-plugin.php:23msgid "You live in $state"msgstr ""
$state = 'Florida';// Lookup is "You live in Florida"
printf( __( 'You live in %s', 'my-plugin' ), $state);
Gotchas
• Line breaks• Empty strings• Formatted strings vs. interpolation• Word order and position
printf( __( 'Hi %s, you live in %s', 'my-plugin' ), $user_name, $state);
printf( __( 'Hi %1$s, you live in %2$s', 'my-plugin‘ ), $user_name, $state);
Best Practices
Best Practices
• Use decent English style• Avoid slang and abbreviations
• Keep text together• Break at paragraphs• Use formatted strings instead of
concatenation• Translate phrases not words
• No unnecessary HTML
• Make no assumptions about the translated text
• Length• Word order• Direction• Punctuation
• Avoid translating URLs that don’t have alternate languages available
Tools
• Pig Latin (http://w.org/plugins/piglatin/)• WP i18n Tools (develop.svn.wordpress.org/trunk/tools/i18n/)• PoEdit (https://poedit.net/)• GlotPress (http://blog.glotpress.org/)• Translate WordPress (https://translate.wordpress.org)
Questions?Twitter: @johnpbloch
Website: https://johnpbloch.comEmail: [email protected]