i18n for Plugin and Theme Developers, WordCamp Milano 2016

Sergey Biryukov
Sergey BiryukovWordPress Developer at Yoast.com
Internationalization for
Plugin and Theme Developers
Sergey Biryukov
WordCamp Milano 2016
Sergey Biryukov
● WordPress Core Contributor at Yoast
yoast.com
● Co-founder of Russian WP community
ru.wordpress.org
● Polyglots, Support, and Meta teams
sergeybiryukov.com
@SergeyBiryukov
Plugins and Themes for the Whole World
● Internationalization (i18n) — providing the ability to translate
● Localization (L10n) — translating to a particular language
Plugins and Themes for the Whole World
● Over 100 languages
● More robust code
● Feedback
● It’s easy
Localized Theme Directories
Localized Plugin Directories
Introduction to gettext
● Text domain
– 'my-plugin'
● Preparing the strings
– <?php echo 'Title'; ?>→<?php _e( 'Title', 'my-plugin' ); ?>
● Language files
– .pot, .po, .mo
Text Domain
● Should match the plugin/theme slug (folder name):
– wp-content/plugins/my-plugin→'my-plugin'
– wp-content/themes/my-theme→'my-theme'
● Should be added to plugin/theme headers:
– Plugin Name: My Plugin
– Version: 1.0
– Text Domain: my-plugin
Text Domain
● Loading the text domain
– load_plugin_textdomain( 'my-plugin', false,
dirname( plugin_basename( __FILE__ ) ) . '/languages' );
– load_theme_textdomain( 'my-theme',
get_template_directory() . '/languages' );
Text Domain
● Loading the text domain
– load_plugin_textdomain( 'my-plugin', false,
dirname( plugin_basename( __FILE__ ) ) . '/languages' );
– load_theme_textdomain( 'my-theme',
get_template_directory() . '/languages' );
● wp-content/languages (WordPress 4.6+)
Preparing the Strings
● Regular strings:
– __( 'Hello world!', 'my-plugin' );
– _e( 'Hello world!', 'my-plugin' );
● Strings with context:
– _x( 'Hello world!', 'post title', 'my-plugin' );
– _ex( 'Hello world!', 'post title', 'my-plugin' );
Preparing the Strings
● Plural forms:
– _n( '%d item', '%d items', $count, 'my-plugin' );
– _nx( '%d item', '%d items', $count, 'comments', 'my-plugin' );
● If the number is not available yet:
– _n_noop( '%d item', '%d items', 'my-plugin' );
– _nx_noop('%d item', '%d items', 'comments', 'my-plugin' );
Preparing the Strings
● Escaping HTML tags:
– esc_html__( 'Hello <em>world</em>!', 'my-plugin' );
– esc_html_e( 'Hello <em>world</em>!', 'my-plugin' );
– esc_html_x( 'Hello <em>world</em>!', 'post title', 'my-plugin' );
● Escaping HTML attributes:
– esc_attr__( 'Hello "world"!', 'my-plugin' );
– esc_attr_e( 'Hello "world"!', 'my-plugin' );
– esc_attr_x( 'Hello "world"!', 'post title', 'my-plugin' );
Preparing the Strings
● Escaping HTML tags and attributes:
– <option value="<?php esc_attr_e( 'value', 'my-plugin' ); ?>">
<?php esc_html_e( 'Option label', 'my-plugin' ); ?>
</option>
● Same, in a longer notation:
– <option value="<?php echo esc_attr( __( 'value', 'my-plugin' ) ); ?>">
<?php echo esc_html( __( 'Option label', 'my-plugin' ) ); ?>
</option>
_e() ≠ echo()
● Don’t use PHP variables, only simple strings:
– _e( $string ); — don’t do that.
● Provide the ability to translate whole phrases, not separate words:
– echo __( 'Hello' ) . ' ' . __( 'world!' ); — don’t do that either.
● Don’t forget the text domain:
– _e( 'Hello world!', 'my-plugin' );
● Remove unnecessary HTML markup from the strings:
– _e( '<p>Hello world!</p>', 'my-plugin' );
Context and Comments
● Context — same string, different translations:
– _x( 'redirect', 'noun', 'my-plugin' );
– _x( 'redirect', 'verb', 'my-plugin' );
● Comments — to explain placeholders in a string:
– /* translators: %s: file name */
__( '%s was deleted.', 'my-plugin' );
Plural Forms
● ???
– _e( "You have $count items.", 'my-plugin' );
– _e( 'You have ' . $count . ' items.', 'my-plugin' );
– printf( __( 'You have %d items.', 'my-plugin' ), $count );
– printf( _n( 'You have %d item.', 'You have %d items.', $count ),
$count );
Plural Forms
● Incorrect:
– _e( "You have $count items.", 'my-plugin' );
– _e( 'You have ' . $count . ' items.', 'my-plugin' );
– printf( __( 'You have %d items.', 'my-plugin' ), $count );
● Almost correct:
– printf( _n( 'You have %d item.', 'You have %d items.', $count ),
$count );
Plural Forms
● Correct:
– printf( _n( 'You have %d item.', 'You have %d items.', $count ),
number_format_i18n( $count ) );
● number_format_i18n() — for displaying numbers
● date_i18n() — for displaying dates
Plural Forms
● If the number is not available:
– $items_plural = _n_noop( 'You have %s item.', 'You have %s items',
'my-plugin' );
● ...
● After it’s available:
– printf( translate_nooped_plural( $items_plural, $count ),
number_format_i18n( $count ) );
● translate_nooped_plural() — for deferred translations of plural strings
Plural Forms
● The first form is not necessarily used for 1 item:
– printf( _n( 'Theme deleted.', '%d themes deleted.', $count ),
number_format_i18n( $count ) );
● Better:
– if ( 1 === $count ) {
_e( 'Theme deleted.' );
– } else {
printf( _n( '%d theme deleted.', '%d themes deleted.', $count ),
number_format_i18n( $count ) );
– }
Language Files
● .pot (Portable Object Template)
– Translation template, contains English strings only.
● .po (Portable Object)
– Language file in a human-readable format.
● .mo (Machine Object)
– Compiled language file in a machine-readable format.
Language Files
makepot.php→.pot→Poedit→.po/.mo→email
Plugin Changelog
● Version 1.5.6
– Added Russian translation.
– That’s it!
● Version 1.5.6.1
– Fixed a typo in Russian translation.
Language Files
makepot.php→.pot→Poedit→.po/.mo→email
translate.wordpress.org
translate.wordpress.org
translate.wordpress.org
● GTE (General Translation Editor) — locale editors
– Can check and approve all translations.
● PTE (Project Translation Editor) — project editors
– Can approve translations for a particular project.
● Translators
– Can suggest translations.
If Someone Has Sent You Their Translation
● Ask them to create a WordPress.org account
– They can be added as a Project Translation Editor.
– They would be able to import the .po file themselves.
– ...and continue translating in the future.
● Ask locale editors to import the files
– No guarantee that the plugin will continue to be actively translated.
If Someone Has Sent You Their Translation
● Once the translator has a WordPress.org account:
– Go to the Polyglots team blog:
https://make.wordpress.org/polyglots/
– Find the Polyglots Handbook link:
https://make.wordpress.org/polyglots/handbook/
– On “Theme & Plugin Directories” page, find a post template for
requesting new translation editors.
– Submit your request to the Polyglots blog and wait for a reply.
@SergeyBiryukov
Thanks! Questions?
1 of 30

Recommended

Writing PHP – The WordPress Way! by Rahul Bansal @WordCamp Mumbai 2017 by
Writing PHP – The WordPress Way! by Rahul Bansal  @WordCamp Mumbai 2017Writing PHP – The WordPress Way! by Rahul Bansal  @WordCamp Mumbai 2017
Writing PHP – The WordPress Way! by Rahul Bansal @WordCamp Mumbai 2017rtCamp
7.8K views26 slides
WordPress&映像配信セミナー+さぶみっと!オフ会 - 第1回 さぶみっと! WEB制作セミナー Supported by NTTスマートコネクト by
WordPress&映像配信セミナー+さぶみっと!オフ会 - 第1回 さぶみっと! WEB制作セミナー Supported by NTTスマートコネクトWordPress&映像配信セミナー+さぶみっと!オフ会 - 第1回 さぶみっと! WEB制作セミナー Supported by NTTスマートコネクト
WordPress&映像配信セミナー+さぶみっと!オフ会 - 第1回 さぶみっと! WEB制作セミナー Supported by NTTスマートコネクトHiromichi Koga
2.2K views96 slides
Building a good quality WordPress theme by
Building a good quality WordPress themeBuilding a good quality WordPress theme
Building a good quality WordPress themeNisha Singh
451 views10 slides
D7 theming what's new - London by
D7 theming what's new - LondonD7 theming what's new - London
D7 theming what's new - LondonMarek Sotak
4K views30 slides
Theme like a monster #ddceu by
Theme like a monster #ddceuTheme like a monster #ddceu
Theme like a monster #ddceuMarek Sotak
932 views24 slides
Drupal 7 Theming - what's new by
Drupal 7 Theming - what's newDrupal 7 Theming - what's new
Drupal 7 Theming - what's newMarek Sotak
2.7K views32 slides

More Related Content

What's hot

Making static sites dynamic (with WordPress yo!) by
Making static sites dynamic (with WordPress yo!)Making static sites dynamic (with WordPress yo!)
Making static sites dynamic (with WordPress yo!)Anthony Montalbano
230 views52 slides
Mojolicious by
MojoliciousMojolicious
MojoliciousMarcos Rebelo
5.4K views44 slides
Mojolicious - A new hope by
Mojolicious - A new hopeMojolicious - A new hope
Mojolicious - A new hopeMarcus Ramberg
12.1K views98 slides
Mojolicious on Steroids by
Mojolicious on SteroidsMojolicious on Steroids
Mojolicious on SteroidsTudor Constantin
3.8K views15 slides
20110820 header new style by
20110820 header new style20110820 header new style
20110820 header new styleAgentiadeturismInvenio
193 views3 slides
Creating Extensible Plugins for WordPress by
Creating Extensible Plugins for WordPressCreating Extensible Plugins for WordPress
Creating Extensible Plugins for WordPressHristo Chakarov
1.4K views26 slides

What's hot(20)

Making static sites dynamic (with WordPress yo!) by Anthony Montalbano
Making static sites dynamic (with WordPress yo!)Making static sites dynamic (with WordPress yo!)
Making static sites dynamic (with WordPress yo!)
Anthony Montalbano230 views
Mojolicious - A new hope by Marcus Ramberg
Mojolicious - A new hopeMojolicious - A new hope
Mojolicious - A new hope
Marcus Ramberg12.1K views
Creating Extensible Plugins for WordPress by Hristo Chakarov
Creating Extensible Plugins for WordPressCreating Extensible Plugins for WordPress
Creating Extensible Plugins for WordPress
Hristo Chakarov1.4K views
Creating a Wordpress Theme from Scratch by Patrick Rauland
Creating a Wordpress Theme from ScratchCreating a Wordpress Theme from Scratch
Creating a Wordpress Theme from Scratch
Patrick Rauland852 views
Make your own wp cli command in 10min by Ivelina Dimova
Make your own wp cli command in 10minMake your own wp cli command in 10min
Make your own wp cli command in 10min
Ivelina Dimova1.4K views
Mojolicious, real-time web framework by taggg
Mojolicious, real-time web frameworkMojolicious, real-time web framework
Mojolicious, real-time web framework
taggg1.6K views
Mojolicious: what works and what doesn't by Cosimo Streppone
Mojolicious: what works and what doesn'tMojolicious: what works and what doesn't
Mojolicious: what works and what doesn't
Cosimo Streppone2.7K views
Develop Netflix Movie Search App using jQuery, OData, JSONP and Netflix Techn... by Doris Chen
Develop Netflix Movie Search App using jQuery, OData, JSONP and Netflix Techn...Develop Netflix Movie Search App using jQuery, OData, JSONP and Netflix Techn...
Develop Netflix Movie Search App using jQuery, OData, JSONP and Netflix Techn...
Doris Chen2.1K views
Let's write secure drupal code! by Balázs Tatár
Let's write secure drupal code!Let's write secure drupal code!
Let's write secure drupal code!
Balázs Tatár297 views
Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk) by Dotan Dimet
Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)
Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)
Dotan Dimet1.4K views
Modern Perl Web Development with Dancer by Dave Cross
Modern Perl Web Development with DancerModern Perl Web Development with Dancer
Modern Perl Web Development with Dancer
Dave Cross2.5K views
Wordless, stop writing WordPress themes like it's 1998 by Filippo Dino
Wordless, stop writing WordPress themes like it's 1998Wordless, stop writing WordPress themes like it's 1998
Wordless, stop writing WordPress themes like it's 1998
Filippo Dino811 views
How to learn j query by Baoyu Xu
How to learn j queryHow to learn j query
How to learn j query
Baoyu Xu1.3K views

Viewers also liked

i18n for Plugin and Theme Developers, WordCamp Moscow 2016 by
i18n for Plugin and Theme Developers, WordCamp Moscow 2016i18n for Plugin and Theme Developers, WordCamp Moscow 2016
i18n for Plugin and Theme Developers, WordCamp Moscow 2016Sergey Biryukov
1.3K views30 slides
Conception de thèmes WordPress : construire et optimiser son espace de travail by
Conception de thèmes WordPress : construire  et optimiser son espace de travailConception de thèmes WordPress : construire  et optimiser son espace de travail
Conception de thèmes WordPress : construire et optimiser son espace de travailFrédérique Game
5.6K views61 slides
How to make your WordPress website multilingual - WordCamp Paris 2016 by
How to make your WordPress website multilingual - WordCamp Paris 2016How to make your WordPress website multilingual - WordCamp Paris 2016
How to make your WordPress website multilingual - WordCamp Paris 2016Matt Pilarski
4.3K views25 slides
WordPress on HHVM + Hack by
WordPress on HHVM + HackWordPress on HHVM + Hack
WordPress on HHVM + HackTakayuki Miyauchi
14.2K views25 slides
Contributing to WordPress, WordCamp Russia 2013 by
Contributing to WordPress, WordCamp Russia 2013Contributing to WordPress, WordCamp Russia 2013
Contributing to WordPress, WordCamp Russia 2013Sergey Biryukov
6.3K views27 slides
Everything You Need to Know About WP_Query, WordCamp Russia 2014 by
Everything You Need to Know About WP_Query, WordCamp Russia 2014Everything You Need to Know About WP_Query, WordCamp Russia 2014
Everything You Need to Know About WP_Query, WordCamp Russia 2014Sergey Biryukov
2.9K views68 slides

Viewers also liked(20)

i18n for Plugin and Theme Developers, WordCamp Moscow 2016 by Sergey Biryukov
i18n for Plugin and Theme Developers, WordCamp Moscow 2016i18n for Plugin and Theme Developers, WordCamp Moscow 2016
i18n for Plugin and Theme Developers, WordCamp Moscow 2016
Sergey Biryukov1.3K views
Conception de thèmes WordPress : construire et optimiser son espace de travail by Frédérique Game
Conception de thèmes WordPress : construire  et optimiser son espace de travailConception de thèmes WordPress : construire  et optimiser son espace de travail
Conception de thèmes WordPress : construire et optimiser son espace de travail
Frédérique Game5.6K views
How to make your WordPress website multilingual - WordCamp Paris 2016 by Matt Pilarski
How to make your WordPress website multilingual - WordCamp Paris 2016How to make your WordPress website multilingual - WordCamp Paris 2016
How to make your WordPress website multilingual - WordCamp Paris 2016
Matt Pilarski4.3K views
Contributing to WordPress, WordCamp Russia 2013 by Sergey Biryukov
Contributing to WordPress, WordCamp Russia 2013Contributing to WordPress, WordCamp Russia 2013
Contributing to WordPress, WordCamp Russia 2013
Sergey Biryukov6.3K views
Everything You Need to Know About WP_Query, WordCamp Russia 2014 by Sergey Biryukov
Everything You Need to Know About WP_Query, WordCamp Russia 2014Everything You Need to Know About WP_Query, WordCamp Russia 2014
Everything You Need to Know About WP_Query, WordCamp Russia 2014
Sergey Biryukov2.9K views
Looking into WordPress Core, WordCamp Russia 2015 by Sergey Biryukov
Looking into WordPress Core, WordCamp Russia 2015Looking into WordPress Core, WordCamp Russia 2015
Looking into WordPress Core, WordCamp Russia 2015
Sergey Biryukov2.3K views
Моделирование контента в WordPress by Anna Ladoshkina
Моделирование контента в WordPressМоделирование контента в WordPress
Моделирование контента в WordPress
Anna Ladoshkina3.4K views
Composer и разработка сайтов на WordPress by Anna Ladoshkina
Composer и разработка сайтов на WordPressComposer и разработка сайтов на WordPress
Composer и разработка сайтов на WordPress
Anna Ladoshkina1.2K views
Managing a Local WordPress Community, WordCamp Europe 2016 by Sergey Biryukov
Managing a Local WordPress Community, WordCamp Europe 2016Managing a Local WordPress Community, WordCamp Europe 2016
Managing a Local WordPress Community, WordCamp Europe 2016
Sergey Biryukov993 views
Практическая доступность с WordPress by Anna Ladoshkina
Практическая доступность с WordPressПрактическая доступность с WordPress
Практическая доступность с WordPress
Anna Ladoshkina1.5K views
Ведение бизнеса на основе WordPress by Andrey Ovsyannikov
Ведение бизнеса на основе WordPressВедение бизнеса на основе WordPress
Ведение бизнеса на основе WordPress
Andrey Ovsyannikov1.8K views
Using Composer to create manageable WordPress websites by Anna Ladoshkina
Using Composer to create manageable WordPress websitesUsing Composer to create manageable WordPress websites
Using Composer to create manageable WordPress websites
Anna Ladoshkina1.2K views
Surviving a Crisis of Confidence by Nathan Ingram
Surviving a Crisis of ConfidenceSurviving a Crisis of Confidence
Surviving a Crisis of Confidence
Nathan Ingram617 views
WordCamp Birmingham 2016 -- Do You Really Need a 3-lb Pocket Knife? by Kate Newbill
WordCamp Birmingham 2016 -- Do You Really Need a 3-lb Pocket Knife?WordCamp Birmingham 2016 -- Do You Really Need a 3-lb Pocket Knife?
WordCamp Birmingham 2016 -- Do You Really Need a 3-lb Pocket Knife?
Kate Newbill366 views
Website Pricing 101: Don’t Be a Commodity by Geoff Myers
Website Pricing 101: Don’t Be a CommodityWebsite Pricing 101: Don’t Be a Commodity
Website Pricing 101: Don’t Be a Commodity
Geoff Myers1.1K views
WCBham Beginner WordPress Security by Gerroald Barron
WCBham Beginner WordPress SecurityWCBham Beginner WordPress Security
WCBham Beginner WordPress Security
Gerroald Barron1.5K views
WordCamp Tokyo2016itkaasan by 松田 千尋
WordCamp Tokyo2016itkaasanWordCamp Tokyo2016itkaasan
WordCamp Tokyo2016itkaasan
松田 千尋11.3K views
Wordcamp Denver 2015 - Get Clear w Diane Whiddon by Diane Whiddon
Wordcamp Denver 2015 - Get Clear w Diane WhiddonWordcamp Denver 2015 - Get Clear w Diane Whiddon
Wordcamp Denver 2015 - Get Clear w Diane Whiddon
Diane Whiddon2.4K views

Similar to i18n for Plugin and Theme Developers, WordCamp Milano 2016

i18n for Plugin and Theme Developers, Global WordPress Translation Day 3 by
i18n for Plugin and Theme Developers, Global WordPress Translation Day 3i18n for Plugin and Theme Developers, Global WordPress Translation Day 3
i18n for Plugin and Theme Developers, Global WordPress Translation Day 3Sergey Biryukov
381 views30 slides
WCRI 2015 I18N L10N by
WCRI 2015 I18N L10NWCRI 2015 I18N L10N
WCRI 2015 I18N L10NDave McHale
290 views42 slides
WordPress internationalization, localization, and multilingual by
WordPress internationalization, localization, and multilingualWordPress internationalization, localization, and multilingual
WordPress internationalization, localization, and multilingualmbigul
2.3K views38 slides
How to make multilingual plugins and themes by
How to make multilingual plugins and themesHow to make multilingual plugins and themes
How to make multilingual plugins and themesjohnpbloch
536 views41 slides
Brian hogg word camp preparing a plugin for translation by
Brian hogg   word camp preparing a plugin for translationBrian hogg   word camp preparing a plugin for translation
Brian hogg word camp preparing a plugin for translationwcto2017
1.7K views93 slides
Sourcerer and Joomla! rev. 20130903 by
Sourcerer and Joomla! rev. 20130903Sourcerer and Joomla! rev. 20130903
Sourcerer and Joomla! rev. 20130903DouglasPickett
2.9K views63 slides

Similar to i18n for Plugin and Theme Developers, WordCamp Milano 2016(20)

i18n for Plugin and Theme Developers, Global WordPress Translation Day 3 by Sergey Biryukov
i18n for Plugin and Theme Developers, Global WordPress Translation Day 3i18n for Plugin and Theme Developers, Global WordPress Translation Day 3
i18n for Plugin and Theme Developers, Global WordPress Translation Day 3
Sergey Biryukov381 views
WCRI 2015 I18N L10N by Dave McHale
WCRI 2015 I18N L10NWCRI 2015 I18N L10N
WCRI 2015 I18N L10N
Dave McHale290 views
WordPress internationalization, localization, and multilingual by mbigul
WordPress internationalization, localization, and multilingualWordPress internationalization, localization, and multilingual
WordPress internationalization, localization, and multilingual
mbigul2.3K views
How to make multilingual plugins and themes by johnpbloch
How to make multilingual plugins and themesHow to make multilingual plugins and themes
How to make multilingual plugins and themes
johnpbloch536 views
Brian hogg word camp preparing a plugin for translation by wcto2017
Brian hogg   word camp preparing a plugin for translationBrian hogg   word camp preparing a plugin for translation
Brian hogg word camp preparing a plugin for translation
wcto20171.7K views
Sourcerer and Joomla! rev. 20130903 by DouglasPickett
Sourcerer and Joomla! rev. 20130903Sourcerer and Joomla! rev. 20130903
Sourcerer and Joomla! rev. 20130903
DouglasPickett2.9K views
WordPress Internationalization, Localization and Multilingual - Do It Right by Dat Hoang
WordPress Internationalization, Localization and Multilingual - Do It RightWordPress Internationalization, Localization and Multilingual - Do It Right
WordPress Internationalization, Localization and Multilingual - Do It Right
Dat Hoang760 views
I18nize Scala programs à la gettext by Ngoc Dao
I18nize Scala programs à la gettextI18nize Scala programs à la gettext
I18nize Scala programs à la gettext
Ngoc Dao2K views
Modern javascript localization with c-3po and the good old gettext by Alexander Mostovenko
Modern javascript localization with c-3po and the good old gettextModern javascript localization with c-3po and the good old gettext
Modern javascript localization with c-3po and the good old gettext
Writing Multilingual Plugins and Themes - WCMIA 2016 by johnpbloch
Writing Multilingual Plugins and Themes - WCMIA 2016Writing Multilingual Plugins and Themes - WCMIA 2016
Writing Multilingual Plugins and Themes - WCMIA 2016
johnpbloch1.4K views
WordPress Internationalization and Localization - WordPress Translation Day 3... by WordPress Trivandrum
WordPress Internationalization and Localization - WordPress Translation Day 3...WordPress Internationalization and Localization - WordPress Translation Day 3...
WordPress Internationalization and Localization - WordPress Translation Day 3...
PHP BASIC PRESENTATION by krutitrivedi
PHP BASIC PRESENTATIONPHP BASIC PRESENTATION
PHP BASIC PRESENTATION
krutitrivedi730 views
Joomla! Frappe - Κατασκευή εφαρμογών για το Joomla! χωρίς να τραβάτε τα μαλιά... by Nicholas Dionysopoulos
Joomla! Frappe - Κατασκευή εφαρμογών για το Joomla! χωρίς να τραβάτε τα μαλιά...Joomla! Frappe - Κατασκευή εφαρμογών για το Joomla! χωρίς να τραβάτε τα μαλιά...
Joomla! Frappe - Κατασκευή εφαρμογών για το Joomla! χωρίς να τραβάτε τα μαλιά...
Using Geeklog as a Web Application Framework by Dirk Haun
Using Geeklog as a Web Application FrameworkUsing Geeklog as a Web Application Framework
Using Geeklog as a Web Application Framework
Dirk Haun894 views
Preparing a WordPress Plugin for Translation by Brian Hogg
Preparing a WordPress Plugin for TranslationPreparing a WordPress Plugin for Translation
Preparing a WordPress Plugin for Translation
Brian Hogg581 views

Recently uploaded

Affiliate Marketing by
Affiliate MarketingAffiliate Marketing
Affiliate MarketingNavin Dhanuka
20 views30 slides
ARNAB12.pdf by
ARNAB12.pdfARNAB12.pdf
ARNAB12.pdfArnabChakraborty499766
5 views83 slides
cis5-Project-11a-Harry Lai by
cis5-Project-11a-Harry Laicis5-Project-11a-Harry Lai
cis5-Project-11a-Harry Laiharrylai126
9 views11 slides
Marketing and Community Building in Web3 by
Marketing and Community Building in Web3Marketing and Community Building in Web3
Marketing and Community Building in Web3Federico Ast
15 views64 slides
ATPMOUSE_융합2조.pptx by
ATPMOUSE_융합2조.pptxATPMOUSE_융합2조.pptx
ATPMOUSE_융합2조.pptxkts120898
35 views70 slides
Amine el bouzalimi by
Amine el bouzalimiAmine el bouzalimi
Amine el bouzalimiAmine EL BOUZALIMI
5 views38 slides

Recently uploaded(10)

i18n for Plugin and Theme Developers, WordCamp Milano 2016

  • 1. Internationalization for Plugin and Theme Developers Sergey Biryukov WordCamp Milano 2016
  • 2. Sergey Biryukov ● WordPress Core Contributor at Yoast yoast.com ● Co-founder of Russian WP community ru.wordpress.org ● Polyglots, Support, and Meta teams sergeybiryukov.com @SergeyBiryukov
  • 3. Plugins and Themes for the Whole World ● Internationalization (i18n) — providing the ability to translate ● Localization (L10n) — translating to a particular language
  • 4. Plugins and Themes for the Whole World ● Over 100 languages ● More robust code ● Feedback ● It’s easy
  • 7. Introduction to gettext ● Text domain – 'my-plugin' ● Preparing the strings – <?php echo 'Title'; ?>→<?php _e( 'Title', 'my-plugin' ); ?> ● Language files – .pot, .po, .mo
  • 8. Text Domain ● Should match the plugin/theme slug (folder name): – wp-content/plugins/my-plugin→'my-plugin' – wp-content/themes/my-theme→'my-theme' ● Should be added to plugin/theme headers: – Plugin Name: My Plugin – Version: 1.0 – Text Domain: my-plugin
  • 9. Text Domain ● Loading the text domain – load_plugin_textdomain( 'my-plugin', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); – load_theme_textdomain( 'my-theme', get_template_directory() . '/languages' );
  • 10. Text Domain ● Loading the text domain – load_plugin_textdomain( 'my-plugin', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); – load_theme_textdomain( 'my-theme', get_template_directory() . '/languages' ); ● wp-content/languages (WordPress 4.6+)
  • 11. Preparing the Strings ● Regular strings: – __( 'Hello world!', 'my-plugin' ); – _e( 'Hello world!', 'my-plugin' ); ● Strings with context: – _x( 'Hello world!', 'post title', 'my-plugin' ); – _ex( 'Hello world!', 'post title', 'my-plugin' );
  • 12. Preparing the Strings ● Plural forms: – _n( '%d item', '%d items', $count, 'my-plugin' ); – _nx( '%d item', '%d items', $count, 'comments', 'my-plugin' ); ● If the number is not available yet: – _n_noop( '%d item', '%d items', 'my-plugin' ); – _nx_noop('%d item', '%d items', 'comments', 'my-plugin' );
  • 13. Preparing the Strings ● Escaping HTML tags: – esc_html__( 'Hello <em>world</em>!', 'my-plugin' ); – esc_html_e( 'Hello <em>world</em>!', 'my-plugin' ); – esc_html_x( 'Hello <em>world</em>!', 'post title', 'my-plugin' ); ● Escaping HTML attributes: – esc_attr__( 'Hello "world"!', 'my-plugin' ); – esc_attr_e( 'Hello "world"!', 'my-plugin' ); – esc_attr_x( 'Hello "world"!', 'post title', 'my-plugin' );
  • 14. Preparing the Strings ● Escaping HTML tags and attributes: – <option value="<?php esc_attr_e( 'value', 'my-plugin' ); ?>"> <?php esc_html_e( 'Option label', 'my-plugin' ); ?> </option> ● Same, in a longer notation: – <option value="<?php echo esc_attr( __( 'value', 'my-plugin' ) ); ?>"> <?php echo esc_html( __( 'Option label', 'my-plugin' ) ); ?> </option>
  • 15. _e() ≠ echo() ● Don’t use PHP variables, only simple strings: – _e( $string ); — don’t do that. ● Provide the ability to translate whole phrases, not separate words: – echo __( 'Hello' ) . ' ' . __( 'world!' ); — don’t do that either. ● Don’t forget the text domain: – _e( 'Hello world!', 'my-plugin' ); ● Remove unnecessary HTML markup from the strings: – _e( '<p>Hello world!</p>', 'my-plugin' );
  • 16. Context and Comments ● Context — same string, different translations: – _x( 'redirect', 'noun', 'my-plugin' ); – _x( 'redirect', 'verb', 'my-plugin' ); ● Comments — to explain placeholders in a string: – /* translators: %s: file name */ __( '%s was deleted.', 'my-plugin' );
  • 17. Plural Forms ● ??? – _e( "You have $count items.", 'my-plugin' ); – _e( 'You have ' . $count . ' items.', 'my-plugin' ); – printf( __( 'You have %d items.', 'my-plugin' ), $count ); – printf( _n( 'You have %d item.', 'You have %d items.', $count ), $count );
  • 18. Plural Forms ● Incorrect: – _e( "You have $count items.", 'my-plugin' ); – _e( 'You have ' . $count . ' items.', 'my-plugin' ); – printf( __( 'You have %d items.', 'my-plugin' ), $count ); ● Almost correct: – printf( _n( 'You have %d item.', 'You have %d items.', $count ), $count );
  • 19. Plural Forms ● Correct: – printf( _n( 'You have %d item.', 'You have %d items.', $count ), number_format_i18n( $count ) ); ● number_format_i18n() — for displaying numbers ● date_i18n() — for displaying dates
  • 20. Plural Forms ● If the number is not available: – $items_plural = _n_noop( 'You have %s item.', 'You have %s items', 'my-plugin' ); ● ... ● After it’s available: – printf( translate_nooped_plural( $items_plural, $count ), number_format_i18n( $count ) ); ● translate_nooped_plural() — for deferred translations of plural strings
  • 21. Plural Forms ● The first form is not necessarily used for 1 item: – printf( _n( 'Theme deleted.', '%d themes deleted.', $count ), number_format_i18n( $count ) ); ● Better: – if ( 1 === $count ) { _e( 'Theme deleted.' ); – } else { printf( _n( '%d theme deleted.', '%d themes deleted.', $count ), number_format_i18n( $count ) ); – }
  • 22. Language Files ● .pot (Portable Object Template) – Translation template, contains English strings only. ● .po (Portable Object) – Language file in a human-readable format. ● .mo (Machine Object) – Compiled language file in a machine-readable format.
  • 24. Plugin Changelog ● Version 1.5.6 – Added Russian translation. – That’s it! ● Version 1.5.6.1 – Fixed a typo in Russian translation.
  • 27. translate.wordpress.org ● GTE (General Translation Editor) — locale editors – Can check and approve all translations. ● PTE (Project Translation Editor) — project editors – Can approve translations for a particular project. ● Translators – Can suggest translations.
  • 28. If Someone Has Sent You Their Translation ● Ask them to create a WordPress.org account – They can be added as a Project Translation Editor. – They would be able to import the .po file themselves. – ...and continue translating in the future. ● Ask locale editors to import the files – No guarantee that the plugin will continue to be actively translated.
  • 29. If Someone Has Sent You Their Translation ● Once the translator has a WordPress.org account: – Go to the Polyglots team blog: https://make.wordpress.org/polyglots/ – Find the Polyglots Handbook link: https://make.wordpress.org/polyglots/handbook/ – On “Theme & Plugin Directories” page, find a post template for requesting new translation editors. – Submit your request to the Polyglots blog and wait for a reply.