 Our next speaker is coming from Zurich, actually he is 25 years old and he is a software engineer and also it's working for Google. I will let him to explain to us how to make our plugins and our WordPress plans to talk our native language. I present you Pascal. Thank you. It's great to be here today. Very impressive location. There are some great talks to part. This one is more for developers. So if that's not something for you, feel free to go outside, talk to sponsors. Please don't go watch a movie. So yeah, my name is Pascal. I'm a software engineer and a WordPress core committer as well. And I came all the way from Switzerland to share some of my WordPress knowledge. And internationalization is one area I particularly like in software development. And this talk is all about how internationalization works in WordPress. If you can see the slides. So if you want to get the slides after my talk, I will publish them on Twitter afterwards. So internationalization is an area in software development that a variety of things. The basics usually stay the same. And however, especially in recent years WordPress has made many improvements in that regard. And there's always new stuff around the corner and ways to improve and existing things. And today I'm going to talk about how things can work in WordPress and how they will work in the future. First, I'm going to explain what it takes to make a WordPress plugin or theme translation ready. Especially going to highlight the differences between projects hosted on WordPress.org and private projects that you might develop for yourself or clients. Second, I'm going to explain how internationalization is handled when building things for Gutenberg, the new buff editor that is coming to WordPress. It doesn't quite turn things upside down, but there's still some new stuff one has to implement. Third, I'm going to show some ways to improve the way we have to deal with WordPress internationalization. In other words, it's about making our lives easier as developers, users and translators. Now let's see what it takes to make a plugin translation ready. I will start by building a new plugin. For this example, we assume that we want to publish it on WordPress.org, just like Jetpack or Yoast, SEL and thousands of others. The most basic part of the most basic WordPress plugin consists of a single PHP file. In this PHP file, we can then use the internationalization functions that WordPress provides to make our plugins translatable. And if we want to just distribute our plugin on WordPress.org, we also have to add a reading file that explains how the plugin works. So in the end, a plugin folder structure looks a bit like this. We have a folder called my-plugin, which contains the plugin file, also named my-plugin-php, and the reading file. And the plugin file in the simplest form looks a bit like this. There's some metadata like plugin name, description, author, version. And at the bottom, for this example, we have some text that we want to translate. This example uses just one of the many translation functions that WordPress provides for this purpose. And the second argument to that function call is the plugin's text domain. In this case, the text domain is also my-plugin, so the same as the folder name from before. It's an important detail that enables WordPress to download translations later on. So these two have to match. Another detail is that in our readme file, we define that the plugin requires at least WordPress 4.6. This is the version where we added some major improvements to the translation system in WordPress and how language packs are downloaded. You don't have to worry about that much, and plus I hope you're all using the latest version of WordPress anyway. Now, we can submit our plugin to the WordPress.org plugin directory. This basically means uploading a sit file and waiting for approval by the plugin review team. And as soon as it gets approved and we upload the final plugin, that will be available under the same name that we used before in the code. So our folder name is my-plugin, the text domain is my-plugin, and the URL to the plugin is now. WordPress.org slash plugins slash my-plugin. So we built our plugin and published it on WordPress.org. That means it can now be translated at translate.wordpress.org. This is the official WordPress translation platform where thousands of people get together to translate plugins, themes, WordPress itself, and even the WordPress mobile apps into thousands of languages. You don't have to do anything special to leverage the platform. As soon as you publish your plugin, it will be available on this site. And the biggest benefit, of course, is that thousands of users use the platform and you have a huge community around it and people can translate your plugin. And now, as soon as you download, like you go to the plugins list in your WordPress admin, you download the plugin, install it, activate it, and then WordPress will automatically install the needed translations directly from the translation platform. And when new translations are available, it will be updated automatically as well. There's nothing else you have to do, it just works. You can easily verify this by checking the language folder inside the WP content. When installing the plugin, WordPress will download the language packs for the plugin to that folder. And even better is that WordPress will actually automatically load these translations as soon as they are needed. We don't have to do anything in our plugin, again, it just works. So essentially, we only have to follow three short steps. First, we develop a new plugin and use the available translation functions to internationalize it. Then we submit it to WordPress org where we can translate it using the translation platform. And after that, WordPress has everything else for us, and our plugin can be fully localized out of the box. Things are, again, a bit more complicated when you develop a private plugin that you don't want to publish anywhere. Maybe it's a plugin for a personal site, a client, or something you want to sell online. Then you can't use WordPress.org for that. The first step, still the same. We have to write a plugin. But after that, we're kind of left on our own. It begins with the so-called string extraction. This is the part where we need to find all the texts in our plugin that are translatable so that we can actually translate them later on. So for example, all parts that are marked bold here in this example are actually translatable in WordPress. This is automatically done on WordPress.org on a translation platform. But for private plugins, we have to do it ourselves. And to extract these strings, there are a few tools that can help us. A popular choice is the free PoEdit translation editor. You simply point PoEdit to a directory and it detects whether the WordPress plugin is a theme, and then extracts all these strings and you can then translate them. There are also some command line tools for developers to use. The oldest and perhaps most common script out there is called MakePop. It is also used by the Grunt WordPress i18 utility tool. However, nowadays it is recommended to use WPCLi for this task, especially since WPCLi is also the thing that is used on WordPress.org. No matter which tool we use, we end up with a so called translation catalog. This PoEdit file can take all extracted strings that we can now translate. And since we are not using the translation platform from WordPress.org, we will save this file inside the plugin folder and not WPContent slash languages. Since we have to use this PoEdit file for the translation, we need to use some tool that can read these files and help us to translate all the strings. You can use PoEdit again, but there are also some alternatives and online platforms. And perhaps when you want your clients to complete the translations, you might end up adding to copy all the text that was spreadsheet and sent these around. It's not really simple. After translating the plugin, you will end up with the same languages files as earlier in the example. These are the language files that WordPress needs and understands. And again, for the private projects, they need to be in the plugin folder and not WPContent. Now, we just have to load them. And since we are not using the translation platform, they won't get loaded automatically, which means we need a function called load plugin text domain. It basically loads all the translations from our languages folder into memory. And whenever WordPress finds a string from our plugin, it checks the memory for the translation. In summary, we have to do lots of manual steps when developing a private plugin. Not only do we have to extract all the strings ourselves, we also don't benefit from the translated community on WordPress.org. Also, we have to manually load translations in our plugin. It doesn't happen automatically. So if we quickly compare these two options side by side, you can see that WordPress is able to do lots of things for us when we publish a plugin on WordPress.org. For private plugins, the whole process is rather complicated. We have to handle the string extractions ourselves and the translation part as well. On WordPress.org, we don't have to worry about that. On the contrary, it even gives us access to a large community of translators that can localize our plugin. Additionally, we benefit from the so-called just-in-time translation loading. Instead of manually loading the translations into memory, WordPress will only load them automatically but only when needed. This would be a WordPress talk in 2018 without any mention of Gutenberg. As you know, the new editor experience for WordPress is going to be released soon, hopefully. This new editor is almost entirely written in JavaScript, which creates new challenges when it comes to internationalization. That's why for WordPress 500 we had to introduce new functionality to make internationalization and localization easier. This affects anyone who wants to build something for Gutenberg and make it translatable. Building something for Gutenberg means you'll likely end up with registering and then queuing multiple JavaScript files. So your plugin might look something like this, where you have some scripts that maybe some are only needed for certain post-types or perhaps only libraries can be used by others. So you end up with many different JavaScript files to be enqueued. In these JavaScript files, you can use the WP-I18N package. Like in this example, you have the same translation functionality basically as in PHP. But the problem with JavaScript internationalization is that we can't just use load plugin text domain to load the actual translations. For one, this only loads the translations on the server side, but we need to make them available client-side for JavaScript. And second, your plugin can potentially contain thousands of translations. But for a given JavaScript file, you only want to allow the translations that are actually needed by that specific file and only when the file is loaded, of course. That's why we introduced a new function called WP-SetScriptTranslations, which handles the loading of translations for a given script title. And all you need to pass is the name of the script that you registered and the text domain of your plugin. And if your plugin is not hosted on WordPress.org, you also want to pass the path to the translations inside your plugin folder. So that WordPress knows where to look for the translations. What's needed for this to work is a new translation file, actually, a JSON format. As you can see in this example, the JSON file does not only contain the text domain and the local as before, but now also the script handle we used to register the script and load the translations. So right now, the easiest way to create these JSON files with the required format is by using an npm library called po2json. As the name implies, it takes an existing PO file and converts it to JSON format. The only downside to that is that the JSON file should actually only contain the translations that are used by the specific particular JavaScript and not every string from the PO file. Unfortunately, po2json can't help with that. So if your plugin is not hosted on WordPress.org, right now you currently need to do this by hand, which is not ideal. If you want to learn more about JavaScript internationalization support in the WordPress 5.0 and the specific file format, you can find the def note on make.wordpress.org. With this new JavaScript translation file, it's clear that things are getting a bit more complex and complicated than what we are used to. There's now even more internationalization overhead resulting from that. So how can we change that? A lot of this overhead can be reused by improving the existing tooling we have. For example, we already have a WP-CLI command to create POPFODs. And it makes sense to extend the family of CLI commands to help make your lives easier. After all, WP-CLI is the official command line interface for WordPress. One thing that I personally want to tackle is a new WP-CLI command for po2json, which solves the problem by reducing the size of the JSON file. So it will work similar to the NPM script I showed before, but it will make sure that the filenames are correct and that the JSON files would only contain the needed strings. This would be already a great improvement and I think we can expect this new command soon. At least just in time for WordPress 5.0. But even with some improved CLI tooling, there's still a lot of work for developers. Having so many manual steps is not sustainable when you develop dozens of private plugins, and it's also prone to errors. And in order to solve this problem, I will try to come up with a solution. We named it Tradutore, which is Italian for translated. Essentially, Tradutore is like the WordPress.org translation platform, but for everyone. It allows you to have the same benefits for private projects as for public ones hosted on WordPress.org. Having your own translation platform means that you can translate all the plugins and themes using a similar, easy-to-use web interface. What you're seeing here is a very simple bare-bones block press install. So block press is the same software that powers translated WordPress.org. It's an open-source WordPress plugin and the creator of it sits right there. Unfortunately, by default, it doesn't look as pretty as WordPress.org, but it gets its job done. But the UI doesn't matter actually in this case, because Tradutore works invisibly under the hood. So using block press, we can easily translate our custom projects into any language we need. And since it's powered by WordPress, we can create new user accounts for our clients or translation agencies who can help with translations for their specific projects. With Tradutore, we try to automate things as much as possible. So right now, it works like this. Whenever you push changes to your WordPress plugin to your source code repository, Tradutore is nullified. Your repository can be anywhere like GitHub, GitLab, Bitbucket, even Sourceforge, if someone use that. It can be private or public as well. And Tradutore then does a string extraction for you and imports all the strings into block press so they can be translated by you and your clients. And every time translations are updated, Tradutore generates the new language packs that the WordPress needs. And this even includes all the JavaScript translation files. And now when you use the plugin on your WordPress site, it will regularly download the new translations from Tradutore. So that means your site's translations are always up to date, just like as if your plugin would be hosted on WordPress.org. And Tradutore will even notify you on Slack about the changes it made. And this way you always know what the current status is and where language packs are being built. All you need now is a way to tell WordPress, hey, for this particular plugin or theme, download the translations from this site instead of WordPress.org. And all other plugins would still work, same and continue to download the language packs from WordPress.org, of course. So to do this, we built a little helper script called Tradutore Registry. And to use it, you just have to specify the plugin's Slack and URL to the API from Tradutore. Which really represents it kind of looks like this. So all our client websites now download translations from either WordPress.org or our own translation platform depending on whether it's a public or private plugin developed by us. One great benefit of that is that it allows us to collaborate on translations and update them without interrupting the development cycle of like projects. So we don't have to do a new deployment just to update translations. And it also means no more sending spreadsheets full of translations back and forth. So if you look at the comparison again from before, Tradutore does all the things we've only been used to from WordPress.org. We never have to do all the manual stuff again. Everything is as automated as possible. And I'd also like to point out that everything I've shown you now and everything I've built to make this happen is open source and freely available on GitHub. This way you can run your own translation platform powered by WordPress. We actually wrote also plenty of documentation about how things work and how you need to set things up. So if you want to learn more about Tradutore, feel free to check it out on GitHub. And if you have any questions about the project, you can ask them there, open issues, perhaps even submit pull requests. Something I could ask a couple of times is if this would be available as a software as a service kind of platform. So you don't have to install and maintain Tradutore yourself. There are no specific plans yet, but if you would be interested in that as well, please let me know. So I hope you got a good enough overview of how things work and under the hood with WordPress in terms of internationalization and now with Tradutore. I know there was a lot of information to process, so if you have any questions, feel free to ask me now or later today. Thank you very much. Good questions. Can we use Tradutore to translate the plugin that is not written by us, but it's not also translation ready? Yeah, you could certainly do that. All you need to do is basically add this code to your site somewhere. And so to tell WordPress, hey, for this plugin load the translation from my site and not from the plugin itself, for example. And do we need to also the PoEdit translation? No, you can just use the web interface to do all the translations. No more PoEdit. Any other questions? Hi, my first question is, you talked about new changes in WordPress that they automatically download to system, you don't have to load them. Does it mean that now, plugins are not required to load this domain? Yes, so your plugin, if it requires WordPress 4.6 or higher and is on web.org, you don't need to use that function anymore. Okay, thank you. And I have four more questions. Does WordPress now extract strings from JavaScript? Tronitory does. WordPress itself doesn't do the string extraction by itself, it's just a tool to manage the translations. Okay, any other questions? Maybe up there somewhere? Yeah, I mean, probably everyone wants coffee right now. So yeah, thanks again for listening.