{"id":236,"date":"2018-11-13T12:13:14","date_gmt":"2018-11-13T12:13:14","guid":{"rendered":"https:\/\/www.visionmate.se\/en\/?p=236"},"modified":"2018-11-13T12:13:14","modified_gmt":"2018-11-13T12:13:14","slug":"internationalization-and-localization-in-wordpress","status":"publish","type":"post","link":"https:\/\/www.visionmate.se\/en\/2018\/11\/13\/internationalization-and-localization-in-wordpress\/","title":{"rendered":"Internationalization and Localization in WordPress"},"content":{"rendered":"<p>When developing a WordPress theme from scratch it\u2019s a good practice to internationalize your theme so it\u2019s available for translation. It will allow people from all over the world to use it in whatever language they need.<\/p>\n<p><strong>What is Internationalization (i18n) and Localization (l10n)?<\/strong><\/p>\n<p><strong>I18n<\/strong> is a process of making your theme translatable. This is the job of the theme developer to get it ready. It\u2019s often abbreviated as i18n because there are 18 letters between the <em>i<\/em> and the <em>n<\/em>.<\/p>\n<p><strong>L10n<\/strong> refers to the process of actually translating your theme to another language. This can be done by the theme\u2019s users. In order to localize the theme it has to be internationalized first. Localization is abbreviated as l10n because there are 10 letters between the <em>l<\/em> and the <em>n<\/em>.<\/p>\n<p><strong>Gettext libraries<\/strong><\/p>\n<p>WordPress uses gettext libraries to load the translations. It has three types of files:<\/p>\n<p><em>POT (Portable Object Template):<\/em> The first step in the translation process. This file is responsible for generating strings that need to be translated. However it doesn&#8217;t contain any translations by itself.<\/p>\n<p><em>PO (Portable Object):<\/em> These files on the other hand contain the translations and the original strings.<\/p>\n<p><em>MO (Machine Object):<\/em> These files are used by functions to load the translations. It\u2019s not human-readable, but they are the most important.<\/p>\n<p><strong>Preparing the Theme<\/strong><\/p>\n<p>Preparing your theme for internationalization is not as complicated as it might seem. WordPress already provides a set of handy functions for that. First of all we need to include a function in functions.php which will load the translations:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">function my_theme_load_theme_textdomain() {\r\n    load_theme_textdomain( 'my-theme', get_template_directory() . '\/languages' );\r\n}\r\nadd_action( \u2018after_setup_theme','my_theme_load_theme_textdomain' );<\/pre>\n<p>The next step is editing text strings. In order to make strings translatable they should not be hardcoded. Wrap the original strings in one of the WordPress <strong>localization functions.<\/strong> The most commonly used functions:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">__()          \/* returns the translation of its argument *\/\r\n\r\n_e()          \/* echos the string to the browser *\/\r\n\r\nesc_html__()  \/* escapes and returns the translation of its argument *\/\r\n\r\nesc_html_e()  \/* escapes and echos the translation of its argument *\/<\/pre>\n<p>Example:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">&lt;h1&gt;&lt;?php __( 'Translatable text goes here', 'theme-domain' ); ?&gt;&lt;\/h1&gt;\r\n&lt;h3&gt;&lt;?php esc_html__( 'Translatable text goes here', 'theme-domain' ); ?&gt;&lt;\/h3&gt;<\/pre>\n<p>Sometimes you need to output variables, date or plurals in your strings. WordPress provides localization functions for all these cases. Check the full list <a href=\"https:\/\/developer.wordpress.org\/themes\/functionality\/internationalization\/\" target=\"_blank\" rel=\"nofollow noopener\">here.<\/a><\/p>\n<p>When your theme files are ready, the next step is to generate POT file. There are a couple of ways to generate POT file that are described <a href=\"https:\/\/developer.wordpress.org\/themes\/functionality\/localization\/\" target=\"_blank\" rel=\"nofollow noopener\">here.<\/a> I usually use Gulp task runner while developing WordPress themes, so I also create POT file using Gulp (see <a href=\"https:\/\/www.npmjs.com\/package\/gulp-wp-pot\" target=\"_blank\" rel=\"nofollow noopener\">gulp-wp-pot<\/a> package).<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">npm install --save-dev gulp-wp-pot\r\n\r\nvar gulp = require('gulp');\r\nvar wpPot = require('gulp-wp-pot');\r\n \r\ngulp.task('default', function () {\r\n    return gulp.src('src\/*.php')\r\n        .pipe(wpPot( {\r\n            domain: 'domain',\r\n            package: 'Example project'\r\n        } ))\r\n        .pipe(gulp.dest('file.pot'));\r\n});<\/pre>\n<p>The plugin looks for strings enclosed in localization functions and creates POT files with these strings. POT file should be delivered along with the theme so users can translate files using Poedit<strong>.<\/strong><\/p>\n<p><a href=\"https:\/\/poedit.net\/download\" target=\"_blank\" rel=\"nofollow noopener\">Poedit<\/a> is an open source application and it&#8217;s the most popular tool for translating WordPress themes. It takes POT file and generates PO and MO files for the appropriate language.<\/p>\n<p><strong>Now your theme is translation ready!<\/strong><\/p>\n<p>Internationalization is not something developers can avoid, it&#8217;s a <strong>must-have<\/strong> today. Besides that if you plan to submit your themes to WordPress.org it&#8217;s a requirement.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When developing a WordPress theme from scratch it\u2019s a good practice to internationalize your theme&#8230;<\/p>\n","protected":false},"author":1,"featured_media":237,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[17],"class_list":["post-236","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-wordpress"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/posts\/236","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/comments?post=236"}],"version-history":[{"count":1,"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/posts\/236\/revisions"}],"predecessor-version":[{"id":238,"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/posts\/236\/revisions\/238"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/media\/237"}],"wp:attachment":[{"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/media?parent=236"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/categories?post=236"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/tags?post=236"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}