{"id":282,"date":"2020-08-20T09:49:25","date_gmt":"2020-08-20T07:49:25","guid":{"rendered":"http:\/\/www.myblog.nguenkam.com\/?p=282"},"modified":"2020-08-20T13:16:07","modified_gmt":"2020-08-20T11:16:07","slug":"internationalization-i18n-with-angular","status":"publish","type":"post","link":"https:\/\/nguenkam.com\/blog\/index.php\/2020\/08\/20\/internationalization-i18n-with-angular\/","title":{"rendered":"Internationalization ( i18n ) With Angular"},"content":{"rendered":"\n<p>Internationalization, often written as i18n, is the process through which products can be prepared to be taken to other countries. It doesn\u2019t just mean being able to change languages; instead it means being to accept different forms of data, different settings to match local customs and different strings of data and process it correctly.<\/p>\n\n\n\n<p>These days, with so many websites to choose from, making applications available and user-friendly to a worldwide audience is important. In this article, we will focus on using the&nbsp;<a href=\"https:\/\/dzone.com\/articles\/learn-how-to-internationalize-and-localize-your-ja\">built-in i18n tool<\/a> in Angular. So, let&#8217;s get started.<\/p>\n\n\n\n<h4>New Angular Project<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>\n# Install Angular CLI globally\nnpm install --global @angular\/cli\n# Create Angular project\nng new ng-internationalization\n# Would you like to add Angular routing? N\n# Which stylesheet format would you like to use? SCSS\n# Go to project's directory\ncd ng-internationalization\n# Open this folder with your favourite editor\ncode . \n# Serve the application\nng serve -o\n<\/code><\/pre>\n\n\n\n<h4>Translations<\/h4>\n\n\n\n<p>Angular&#8217;s default locale is set to&nbsp;<code>en-US<\/code>. To support more languages, we need to update the default configuration and add additional locales. You can find a list of various locale codes&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/ladjs\/i18n-locales\" target=\"_blank\">here<\/a>. <\/p>\n\n\n\n<h4>Text Marking<\/h4>\n\n\n\n<p>To be able to translate the context in the application, we first need to mark the text with a custom attribute, named&nbsp;<code>i18n<\/code>. After the text marking, we will be able to translate the application into our desire languages. In our case&nbsp;<code>el-GR<\/code>&nbsp;and&nbsp;<code>fr-FR<\/code>. I will be using Google Translate to translate the text into French.<\/p>\n\n\n\n<p>Let&#8217;s add the&nbsp;<code>i18n<\/code>&nbsp;attribute to all of the text that we want to translate<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;main>\n  &lt;section>\n    &lt;h1 i18n>Why is Internationalization so important?&lt;\/h1>\n    &lt;p i18n>\n      These days, with so many websites to choose from, making applications\n      available and user-friendly to a worldwide audience is important. It's the\n      move to make a better user experience.\n    &lt;\/p>\n    &lt;small i18n\n      >Find the full article\n      &lt;a\n        href=\"https:\/\/github.com\/ThPadelis\/ng-internationalization\"\n        target=\"_blank\"\n        >here&lt;\/a\n      >&lt;\/small\n    >\n  &lt;\/section>\n&lt;\/main><\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<hr>\n<p> <strong>i18n  is a custom attribute, recognized by Angular tools and compilers. After translation, the compiler removes it. It is not an Angular directive. <\/strong><\/p>\n<hr>\n\n\n\n<p>Now, we need a&nbsp;<code>script<\/code>&nbsp;that uses the&nbsp;<a href=\"https:\/\/dzone.com\/articles\/getting-started-and-testing-with-angular-cli-and-angular-2-rc5-part-1\">Angular CLI<\/a>&nbsp;to extract this into a&nbsp;<code>messages.xlf<\/code>&nbsp;file. This file contains all of our marked items. Head over to&nbsp;<code>packages.json<\/code>&nbsp;and add this script<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\"scripts\": {\n    \"i18n:extract\": \"ng xi18n --output-path src\/locales\"\n}<\/code><\/pre>\n\n\n\n<p>After adding this script, go ahead and run&nbsp;<code>npm run i18n:extract<\/code>. Then, open up&nbsp;<code>scr\/locales\/messages.xlf<\/code>&nbsp;and you will see something like this<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n&lt;xliff version=\"1.2\" xmlns=\"urn:oasis:names:tc:xliff:document:1.2\">\n  &lt;file source-language=\"en\" datatype=\"plaintext\" original=\"ng2.template\">\n    &lt;body>\n      &lt;trans-unit id=\"4bcef995bebcf205074f9fd756b822a488b452cc\" datatype=\"html\">\n        &lt;source>Why is Internationalization so important?&lt;\/source>\n        &lt;context-group purpose=\"location\">\n          &lt;context context-type=\"sourcefile\">src\/app\/app.component.html&lt;\/context>\n          &lt;context context-type=\"linenumber\">3&lt;\/context>\n        &lt;\/context-group>\n      &lt;\/trans-unit>\n      &lt;trans-unit id=\"e8db4c58a5fc95a2a8d80183e4b527f4480fa06e\" datatype=\"html\">\n        &lt;source>\n      These days, with so many websites to choose from, making applications\n      available and user-friendly to a worldwide audience is important. It's the\n      move to make a better user experience.\n    &lt;\/source>\n        &lt;context-group purpose=\"location\">\n          &lt;context context-type=\"sourcefile\">src\/app\/app.component.html&lt;\/context>\n          &lt;context context-type=\"linenumber\">4&lt;\/context>\n        &lt;\/context-group>\n      &lt;\/trans-unit>\n      &lt;trans-unit id=\"0f16c7aaa76d2f52dbabcd329ebf11a39a26918d\" datatype=\"html\">\n        &lt;source>Find the full article\n      &lt;x id=\"START_LINK\" ctype=\"x-a\" equiv-text=\"&lt;a>\"\/>here&lt;x id=\"CLOSE_LINK\" ctype=\"x-a\" equiv-text=\"&lt;\/a>\"\/>&lt;\/source>\n        &lt;context-group purpose=\"location\">\n          &lt;context context-type=\"sourcefile\">src\/app\/app.component.html&lt;\/context>\n          &lt;context context-type=\"linenumber\">10&lt;\/context>\n        &lt;\/context-group>\n      &lt;\/trans-unit>\n    &lt;\/body>\n  &lt;\/file>\n&lt;\/xliff><\/code><\/pre>\n\n\n\n<p>For each&nbsp;<code>html<\/code>&nbsp;element marked with the&nbsp;<code>i18n<\/code>&nbsp;directive, a&nbsp;<code>trans-unit<\/code>&nbsp;will be created.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;trans-unit id=\"4bcef995bebcf205074f9fd756b822a488b452cc\" datatype=\"html\">\n    &lt;source>Why is Internationalization so important?&lt;\/source>\n    &lt;context-group purpose=\"location\">\n        &lt;context context-type=\"sourcefile\">src\/app\/app.component.html&lt;\/context>\n        &lt;context context-type=\"linenumber\">3&lt;\/context>\n    &lt;\/context-group>\n&lt;\/trans-unit><\/code><\/pre>\n\n\n\n<p>We can provide more information about the translations using this structure by adding a&nbsp;<code>description<\/code>. Inside of&nbsp;<code>app.component.hmtl<\/code>, update the&nbsp;<code>i18n<\/code>&nbsp;items with a description.<\/p>\n\n\n\n<p>Additionally, we can help the translator with a&nbsp;<code>description<\/code>&nbsp;and a&nbsp;<code>meaning<\/code>&nbsp;.<\/p>\n\n\n\n<p>We can also set a custom id for persistence and maintenance. aber all these are optional. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!-- i18n=\"&lt;meanin>|&lt;description>@@customId\" -->\n&lt;h1 i18n=\"Article Heading|Title for the article@@articleHeading\">\n    Why is Internationalization so important?\n&lt;\/h1><\/code><\/pre>\n\n\n\n<p><strong>We can finally generate our translations<\/strong>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\nnpm run i18n:extract<\/code><\/pre>\n\n\n\n<h4>Translations<\/h4>\n\n\n\n<p>At this point, we have a&nbsp;<code>messages.xlf<\/code>&nbsp;file that contains all of the items that we want to translate. Let&#8217;s create a copy of&nbsp;<code>messages.xlf<\/code>&nbsp;for each language we want to translate the application.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cp src\\locales\\messages.xlf src\\locales\\messages.fr.xlf\ncp src\\locales\\messages.xlf src\\locales\\messages.el.xlf<\/code><\/pre>\n\n\n\n<p>Let&#8217;s start with&nbsp;<code>messages.fr.xlf<\/code>. We will translate the messages by using the&nbsp;<code>target<\/code>&nbsp;and &nbsp;<code>source<\/code>. The&nbsp;<code>target<\/code>&nbsp;attribute is the translation in that language.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n&lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n&lt;xliff version=\"1.2\" xmlns=\"urn:oasis:names:tc:xliff:document:1.2\">\n  &lt;file source-language=\"en\" datatype=\"plaintext\" original=\"ng2.template\">\n    &lt;body>\n      &lt;trans-unit id=\"articleHeading\" datatype=\"html\">\n        &lt;source>Why is Internationalization so important?&lt;\/source>\n        &lt;target>Pourquoi l'internationalisation est-elle si importante?&lt;\/target>\n        &lt;context-group purpose=\"location\">\n          &lt;context context-type=\"sourcefile\">src\/app\/app.component.html&lt;\/context>\n          &lt;context context-type=\"linenumber\">3&lt;\/context>\n        &lt;\/context-group>\n        &lt;note priority=\"1\" from=\"description\">Title for the article&lt;\/note>\n        &lt;note priority=\"1\" from=\"meaning\">Article Heading&lt;\/note>\n      &lt;\/trans-unit>\n      &lt;trans-unit id=\"articleDescription\" datatype=\"html\">\n        &lt;source>These days, with so many websites to choose from, making applications available and user-friendly to a worldwide audience is important. It's the move to make a better user experience.&lt;\/source>\n        &lt;target>Ces jours-ci, avec autant de sites Web \u00e0 choisir, il est important de rendre les applications disponibles et conviviales pour un public mondial. C'est le geste d'am\u00e9liorer l'exp\u00e9rience utilisateur.&lt;\/target>\n        &lt;context-group purpose=\"location\">\n          &lt;context context-type=\"sourcefile\">src\/app\/app.component.html&lt;\/context>\n          &lt;context context-type=\"linenumber\">8&lt;\/context>\n        &lt;\/context-group>\n        &lt;note priority=\"1\" from=\"description\">Description for the article&lt;\/note>\n        &lt;note priority=\"1\" from=\"meaning\">Article Description&lt;\/note>\n      &lt;\/trans-unit>\n      &lt;trans-unit id=\"fullArticle\" datatype=\"html\">\n        &lt;source>Find the full article &lt;x id=\"START_LINK\" ctype=\"x-a\" equiv-text=\"&lt;a>\"\/>here&lt;x id=\"CLOSE_LINK\" ctype=\"x-a\" equiv-text=\"&lt;\/a>\"\/>&lt;\/source>\n        &lt;target>Retrouvez l'article complet &lt;x id=\"START_LINK\" ctype=\"x-a\" equiv-text=\"&lt;a>\"\/>ici&lt;x id=\"CLOSE_LINK\" ctype=\"x-a\" equiv-text=\"&lt;\/a>\"\/>&lt;\/target>\n        &lt;context-group purpose=\"location\">\n          &lt;context context-type=\"sourcefile\">src\/app\/app.component.html&lt;\/context>\n          &lt;context context-type=\"linenumber\">14&lt;\/context>\n        &lt;\/context-group>\n        &lt;note priority=\"1\" from=\"description\">Read the whole article&lt;\/note>\n        &lt;note priority=\"1\" from=\"meaning\">Full Article&lt;\/note>\n      &lt;\/trans-unit>\n    &lt;\/body>\n  &lt;\/file>\n&lt;\/xliff><\/code><\/pre>\n\n\n\n<h3>Locale Build Configuration<\/h3>\n\n\n\n<p>Now, we have different versions of our application.&nbsp;A good practice is to have a&nbsp;<code>script<\/code>&nbsp;that builds the application for each locale we want to support.<\/p>\n\n\n\n<p>Head over to&nbsp;<code>angular.json<\/code>&nbsp;and add the below configurations.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"projects\": {\n    \"ng-internationalization\": {\n      \"architect\": {\n        \"build\": {\n          \"configurations\": {\n            \"fr-FR\": {\n              \"aot\": true,\n              \"outputPath\": \"dist\/fr-FR\",\n              \"i18nFile\": \"src\/locales\/messages.fr.xlf\",\n              \"i18nFormat\": \"xlf\",\n              \"i18nLocale\": \"fr\",\n              \"i18nMissingTranslation\": \"error\"\n            },\n            \"el-GR\": {\n              \"aot\": true,\n              \"outputPath\": \"dist\/el-GR\",\n              \"i18nFile\": \"src\/locales\/messages.el.xlf\",\n              \"i18nFormat\": \"xlf\",\n              \"i18nLocale\": \"el-GR\",\n              \"i18nMissingTranslation\": \"error\"\n            }\n          }\n        },\n        \"serve\": {\n          \"configurations\": {\n            \"production\": {\n              \"browserTarget\": \"ng-internationalization:build:production\"\n            },\n            \"fr-FR\": {\n              \"browserTarget\": \"ng-internationalization:build:fr-FR\"\n            },\n            \"el-GR\": {\n              \"browserTarget\": \"ng-internationalization:build:el-GR\"\n            }\n          }\n        }\n      }\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<p>Let&#8217;s create some more scripts inside the package.json file to be able to build and serve our new locales.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\"scripts\": {\n    \"start\": \"ng serve\",\n    \"start:fr\": \"ng serve --configuration=fr-FR\",\n    \"start:gr\": \"ng serve --configuration=el-GR\",\n    \"build\": \"ng build\",\n    \"build:fr\": \"ng build --configuration=fr-FR\",\n    \"build:gr\": \"ng build --configuration=el-GR\",\n}<\/code><\/pre>\n\n\n\n<p>It&#8217;s time to see what we have created.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\nnpm run start\nnpm run start:fr -- --port 4201\nnpm run start:gr -- --port 4202<\/code><\/pre>\n\n\n\n<h4>Conclusion<\/h4>\n\n\n\n<p>Internationalization and localization are important parts of an application. We can use&nbsp;<code>angular-cli<\/code>&nbsp;to support it or install an external library to save some time.<\/p>\n\n\n\n<h4>reference<\/h4>\n\n\n\n<p><a href=\"https:\/\/dzone.com\/articles\/internationalization-i18n-with-angular-1\">https:\/\/dzone.com\/articles\/internationalization-i18n-with-angular-1<\/a><\/p>\n\n\n\n<h5>related \/ usefull Links<\/h5>\n\n\n\n<p><a href=\"https:\/\/angular.io\/api\/core\/MissingTranslationStrategy\" data-type=\"URL\" data-id=\"https:\/\/angular.io\/api\/core\/MissingTranslationStrategy\" target=\"_blank\" rel=\"noreferrer noopener\">MissingTranslationStrategy<\/a><\/p>\n\n\n\n<p class=\"has-white-color has-text-color\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Internationalization, often written as i18n, is the process through which products can be prepared to be taken to other countries. It doesn\u2019t just mean being able to change languages; instead it means being to accept different forms of data, different settings to match local customs and different strings of data and process it correctly. These [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":285,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1,37,44],"tags":[40,47,45,46],"_links":{"self":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/282"}],"collection":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=282"}],"version-history":[{"count":9,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/282\/revisions"}],"predecessor-version":[{"id":314,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/282\/revisions\/314"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/media\/285"}],"wp:attachment":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=282"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=282"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=282"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}