{"id":8721,"date":"2023-07-17T10:56:00","date_gmt":"2023-07-17T08:56:00","guid":{"rendered":"https:\/\/phraseapp.com\/blog\/?p=4624"},"modified":"2023-09-15T09:11:42","modified_gmt":"2023-09-15T07:11:42","slug":"react-native-i18n-with-expo-and-i18next-part-1","status":"publish","type":"post","link":"https:\/\/phrase.com\/blog\/posts\/react-native-i18n-with-expo-and-i18next-part-1\/","title":{"rendered":"A Comprehensive Guide to React Native Localization"},"content":{"rendered":"\n<div id=\"acf\/text-block_04beb40e1a8de9bff2f3ee607a2972ce\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>With <a href=\"https:\/\/www.npmjs.com\/package\/react-native\">over 1.4M downloads per week<\/a> at the time of writing, React Native has proven itself a smash hit when it comes to cross-platform mobile development. Writing React apps in JavaScript that render natively means performant mobile apps can be created by web developers. It\u2019s little wonder that the teams behind the mobile apps for Shopify, Uber Eats, Pinterest, and Discord <a href=\"https:\/\/infostride.com\/apps-built-with-react-native\/\">are using React Native<\/a> to share code between their Android and iOS apps.<\/p>\n<p>The <a href=\"https:\/\/www.npmjs.com\/package\/expo\">popular<\/a> <a href=\"https:\/\/expo.dev\/\">Expo framework<\/a> offers a lot of helpful features on top of React Native, including easy setup and testing, over-the-air updates, and seamless internationalization (i18n) and localization (l10n). The latter is exactly what we&#8217;ll tackle in this guide: Localizing a React Native app with Expo\u2019s powerful i18n features.<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_69_1 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Overview<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/phrase.com\/blog\/posts\/react-native-i18n-with-expo-and-i18next-part-1\/#getting-ready-for-react-native-localization-package-versions\" title=\"Getting ready for React Native localization: Package versions\">Getting ready for React Native localization: Package versions<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/phrase.com\/blog\/posts\/react-native-i18n-with-expo-and-i18next-part-1\/#getting-started\" title=\"Getting started\">Getting started<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/phrase.com\/blog\/posts\/react-native-i18n-with-expo-and-i18next-part-1\/#getting-users-language-and-locale\" title=\"Getting user\u2019s language and locale\">Getting user\u2019s language and locale<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/phrase.com\/blog\/posts\/react-native-i18n-with-expo-and-i18next-part-1\/#returning-localized-strings\" title=\"Returning localized strings\">Returning localized strings<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/phrase.com\/blog\/posts\/react-native-i18n-with-expo-and-i18next-part-1\/#interpolation\" title=\"Interpolation\">Interpolation<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/phrase.com\/blog\/posts\/react-native-i18n-with-expo-and-i18next-part-1\/#localizing-currency\" title=\"Localizing currency\">Localizing currency<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/phrase.com\/blog\/posts\/react-native-i18n-with-expo-and-i18next-part-1\/#number-formatting\" title=\"Number formatting\">Number formatting<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/phrase.com\/blog\/posts\/react-native-i18n-with-expo-and-i18next-part-1\/#localizing-dates\" title=\"Localizing dates\">Localizing dates<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/phrase.com\/blog\/posts\/react-native-i18n-with-expo-and-i18next-part-1\/#plurals\" title=\"Plurals\">Plurals<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/phrase.com\/blog\/posts\/react-native-i18n-with-expo-and-i18next-part-1\/#complex-plurals\" title=\"Complex plurals\">Complex plurals<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/phrase.com\/blog\/posts\/react-native-i18n-with-expo-and-i18next-part-1\/#localizing-measurement\" title=\"Localizing measurement\">Localizing measurement<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/phrase.com\/blog\/posts\/react-native-i18n-with-expo-and-i18next-part-1\/#change-language-from-within-the-application\" title=\"Change Language from within the Application\">Change Language from within the Application<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/phrase.com\/blog\/posts\/react-native-i18n-with-expo-and-i18next-part-1\/#adding-right-to-left-support\" title=\"Adding right-to-left support\">Adding right-to-left support<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/phrase.com\/blog\/posts\/react-native-i18n-with-expo-and-i18next-part-1\/#wrapping-up-our-react-native-localization-guide\" title=\"Wrapping up our React Native localization guide\">Wrapping up our React Native localization guide<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"getting-ready-for-react-native-localization-package-versions\"><\/span>Getting ready for React Native localization: Package versions<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>For this tutorial we will be using the following packages.<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/expo\/expo\">expo<\/a> (48.0.11)<\/li>\n<li><a href=\"https:\/\/www.npmjs.com\/package\/expo-localization\">expo-localization<\/a> (14.1.1)<\/li>\n<li><a href=\"https:\/\/fnando.github.io\/i18n\/v4.2.3\/\">i18n-js<\/a> (4.3.4)<\/li>\n<li><a href=\"https:\/\/github.com\/eemeli\/make-plural\/\">make-plural<\/a> (7.3.0)<\/li>\n<li><a href=\"https:\/\/github.com\/facebook\/react-native\">react-native<\/a> (0.71.6)<\/li>\n<li><a href=\"https:\/\/github.com\/facebook\/react\">react<\/a> (18.2.0)<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"getting-started\"><\/span>Getting started<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>For this tutorial we will internationalise and localize a weather application.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-57162 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230423_162415_Expo-Go-473x1024.jpg\" alt=\"Simple weather app | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230423_162415_Expo-Go-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230423_162415_Expo-Go-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230423_162415_Expo-Go-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230423_162415_Expo-Go-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230423_162415_Expo-Go-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230423_162415_Expo-Go.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/p>\n<p>Our simple weather app consists of a greeting at the top, a weather icon, description and temperature. You can find the starting point on <a href=\"https:\/\/github.com\/PhraseApp-Blog\/React-native-i18n\/tree\/start\">Github<\/a>.<\/p>\n<p>\ud83d\uddd2\ufe0f Note \u00bb For brevity, our app will not fetch weather from any service. We will instead mock the weather data.<\/p>\n<h2 style=\"text-align: left;\"><span class=\"ez-toc-section\" id=\"getting-users-language-and-locale\"><\/span>Getting user\u2019s language and locale<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>First we need to be able to get a user\u2019s system default language and locale. You can use a package called <code>expo-localization<\/code>. This package provides a simple API for detecting the user&#8217;s language and country, as well as for formatting dates and times according to the user&#8217;s locale.<\/p>\n<p>To install this package, run the following command in your project directory:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">\nnpm install expo-localization<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_aa8bcedf0889abdf9c5326f45e5bf3ad\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>In <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">App.js<\/span> file, add the following code:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ .\/App.js<\/span>\n<span class=\"hljs-comment\">\/\/ ...<\/span>\n<span class=\"hljs-keyword\">import<\/span> React, { useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>\n<span class=\"hljs-keyword\">import<\/span> { Text } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'react-native'<\/span>\n<span class=\"hljs-keyword\">import<\/span> * <span class=\"hljs-keyword\">as<\/span> Localization <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'expo-localization\n\nexport default function App() {\n  \/\/...\n  let &#91;locale, setLocale] = useState(Localization.locale)\n\n  return (\n    &lt;&gt;\n      &lt;Container&gt;\n          &lt;Text&gt;{locale}&lt;\/Text&gt;\n           \/\/ ...\n      &lt;\/Container&gt;\n    &lt;\/&gt;\n  );\n}<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_d6c175dc5db9ff71e0991251f824c511\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>On reloading the app, you can now see the user\u2019s locale displaying as <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">en-IN<\/span>. In this case the user\u2019s language is set to English and region is set to India.<\/p>\n<h2><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-57182 size-large aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_014142_Expo-Go-473x1024.jpg\" alt=\"Simple weather app with user's locale displayed | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_014142_Expo-Go-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_014142_Expo-Go-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_014142_Expo-Go-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_014142_Expo-Go-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_014142_Expo-Go-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_014142_Expo-Go.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/h2>\n<h2><span class=\"ez-toc-section\" id=\"returning-localized-strings\"><\/span>Returning localized strings<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The app currently consists of some hard-coded text. We\u2019d like to be able to localize these. If the user changes the language of their phone in their system settings, we want UI strings like \u201cHello\u201d and \u201cBuy premium version for 14.99$\u201d to show in the user\u2019s system default language.<\/p>\n<p>We will use the <a href=\"https:\/\/www.npmjs.com\/package\/i18n-js\">i18n-js<\/a> package to localize our UI strings. To install this package, run the following command in your project directory:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">npm expo install i18n-js<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_c9df33a77a1338691c7eaeb10d7742ea\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>Now create a new file <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">localization.js<\/span> in the <span class=\"discussion-id-5e31b165-5951-49ee-8f90-befe784750bc notion-enable-hover\" data-token-index=\"3\">project root directory<\/span> and add the following code:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ .\/localization.js<\/span>\n<span class=\"hljs-keyword\">const<\/span> translations = {\n    <span class=\"hljs-attr\">en<\/span> : {\n        <span class=\"hljs-attr\">greeting<\/span>: <span class=\"hljs-string\">\"Hello\"<\/span>,\n        <span class=\"hljs-attr\">subscribe<\/span> : <span class=\"hljs-string\">\"Buy premium version for 14.99$\"<\/span>\n    },\n\n    <span class=\"hljs-attr\">de<\/span> :{\n        <span class=\"hljs-attr\">greeting<\/span>: <span class=\"hljs-string\">\"Hallo\"<\/span>,\n        <span class=\"hljs-attr\">subscribe<\/span>: <span class=\"hljs-string\">\"HoKaufen Sie die Premium-Version f\u00fcr 14.99$\"<\/span>\n    }\n\n}\n<span class=\"hljs-keyword\">export<\/span> { translations };<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_e07c0b883bf62c300d1bf33a447dfe5d\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>The keys in the above example can either be language codes or language and region codes.<\/p>\n<p>Here are some examples:<\/p>\n<ul>\n<li>Language codes: en (English), fr (French), zh (Chinese), ru (Russian), ar (Arabic), hi (Hindi)<\/li>\n<li>Language region codes: en-US (English &#8211; United States), en-GB (English &#8211; United Kingdom), zh-CN (Chinese &#8211; China), ru-RU (Russian &#8211; Russia), pt-BR (Portuguese &#8211; Brazil)<\/li>\n<\/ul>\n<p>i18n-js follows the <a href=\"https:\/\/en.wikipedia.org\/wiki\/IETF_language_tag\">BCP 47<\/a> language tag format, which consists of a language code followed by an optional region code separated by a hyphen. This allows for more specific localization based on language and region combinations. Our app will support English (<code>en<\/code>) and German (<code>de<\/code>). Feel free to use any languages (and regions) you want.<\/p>\n<p>Now in <code>App.js<\/code>, make the following changes:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ .\/App.js<\/span>\n\n<span class=\"hljs-comment\">\/\/ ...<\/span>\n<span class=\"hljs-keyword\">import<\/span> React, { useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> * <span class=\"hljs-keyword\">as<\/span> Localization <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'expo-localization'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { I18n } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'i18n-js'<\/span>\n<span class=\"hljs-keyword\">import<\/span> { translations } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'.\/localization'<\/span>;\n\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\t<span class=\"hljs-keyword\">const<\/span> i18n = <span class=\"hljs-keyword\">new<\/span> I18n(translations)\n  <span class=\"hljs-keyword\">let<\/span> &#91;locale, setLocale] = useState(Localization.locale)\n  i18n.locale = locale\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Container<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Text<\/span>&gt;<\/span>{locale}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Text<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Text<\/span>&gt;<\/span>{i18n.t('greeting')}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Text<\/span>&gt;<\/span>\n        \/\/...\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Text<\/span>&gt;<\/span>{i18n.t('subscribe')}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Text<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Container<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/&gt;<\/span><\/span>\n  );\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_36012cfa912b16a7b87638a4dba1a392\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>On reloading the app, you will now see an error. This happens because the phone\u2019s locale is set to <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">en-IN<\/span> while we only have defined languages <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"3\">en<\/span> and <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"5\">de<\/span> in the<span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"7\"> localization.js <\/span>file.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-57188 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_023838_Expo-Go-473x1024.jpg\" alt=\"Reloaded app with an error | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_023838_Expo-Go-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_023838_Expo-Go-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_023838_Expo-Go-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_023838_Expo-Go-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_023838_Expo-Go-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_023838_Expo-Go.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/p>\n<p>To fix this, make the following changes to <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">App.js<\/span><\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ .\/App.js<\/span>\n\n<span class=\"hljs-comment\">\/\/...<\/span>\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> i18n = <span class=\"hljs-keyword\">new<\/span> I18n(translations)\n  i18n.locale = Localization.locale\n  i18n.enableFallback = <span class=\"hljs-literal\">true<\/span>\n  i18n.defaultLocale = <span class=\"hljs-string\">\"en\"<\/span>\n\n<span class=\"hljs-comment\">\/\/...<\/span>\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_fb211c7e75f430e3f2d9d50f5259c2b9\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>By setting <code>i18n.enableFallback = true<\/code> , we make sure that if a user\u2019s locale (<code>en-IN<\/code>) isn\u2019t supported, i18n falls back to our English (<code>en<\/code>) translation messages. Similarly, if we had a user with the <code>de-BE<\/code> locale (German-Belgium), they would see our German (<code>de<\/code>) translations.<\/p>\n<p>However this isn\u2019t sufficient. There could be a scenario where the user\u2019s <em>language<\/em> isn\u2019t supported. In that case, it is a good idea to set a default locale for i18n. We\u2019re using <code>en<\/code> as the default locale here. This ensures that if the user\u2019s language isn\u2019t supported by the app, the user will still see our English translations and never get the above error.<\/p>\n<p>Now after reloading the app, you will notice that the app respects user\u2019s locale.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-57194 size-large aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_025952_Expo-Go-473x1024.jpg\" alt=\"App locale is set to en-IN | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_025952_Expo-Go-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_025952_Expo-Go-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_025952_Expo-Go-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_025952_Expo-Go-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_025952_Expo-Go-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_025952_Expo-Go.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-57200 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_025952_Expo-Go-1-473x1024.jpg\" alt=\"App locale is set to de-DE | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_025952_Expo-Go-1-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_025952_Expo-Go-1-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_025952_Expo-Go-1-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_025952_Expo-Go-1-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_025952_Expo-Go-1-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230424_025952_Expo-Go-1.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/p>\n<h2><span class=\"ez-toc-section\" id=\"interpolation\"><\/span>Interpolation<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Currently the string &#8220;Buy premium version for 14.99$\u201d doesn\u2019t use the <code>price<\/code> that is returned from the API field.<\/p>\n<p>\ud83d\uddd2\ufe0f Note \u00bb To keep this tutorial brief, we are mocking an API response instead of fetching it using network.<\/p>\n<p>In <code>App.js<\/code>, we have defined a mock response:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ .\/App.js<\/span>\n\n<span class=\"hljs-keyword\">const<\/span> dailyWeatherMock = {\n  <span class=\"hljs-attr\">main<\/span>: <span class=\"hljs-string\">\"clouds\"<\/span>,\n  <span class=\"hljs-attr\">description<\/span>: <span class=\"hljs-string\">\"broken_clouds\"<\/span>,\n  <span class=\"hljs-attr\">icon<\/span>: <span class=\"hljs-string\">\"04n\"<\/span>,\n  <span class=\"hljs-attr\">maxInCelsius<\/span>: <span class=\"hljs-number\">9.2<\/span>,\n  <span class=\"hljs-attr\">maxInFahrenheit<\/span>: <span class=\"hljs-number\">9.2<\/span>,\n  <span class=\"hljs-attr\">currentInCelsius<\/span>: <span class=\"hljs-number\">6<\/span>,\n  <span class=\"hljs-attr\">currentInFahrenheit<\/span>:<span class=\"hljs-number\">6<\/span>,\n  <span class=\"hljs-attr\">price<\/span>:<span class=\"hljs-number\">18.99<\/span>,\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_3831fac0d38cfa07ac9f0f61145ea35f\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>We need to inject the price into our translation strings instead of hard-coding it. Go to the <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">localization.js<\/span> file and make the following changes:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Diff\" data-shcb-language-slug=\"diff\"><span><code class=\"hljs language-diff\">\/\/ .\/localization.js\n\nconst translations = {\n    en : {\n        greeting: \"Hello\",\n<span class=\"hljs-deletion\">-       subscribe : \"Buy premium version for 14.99$\"<\/span>\n<span class=\"hljs-addition\">+       subscribe : \"Buy premium version for %{price}\",<\/span>\n    },\n\n    de :{\n        greeting: \"Hallo\",\n<span class=\"hljs-deletion\">-       subscribe: \"HoKaufen Sie die Premium-Version f\u00fcr 14.99$\"<\/span>\n<span class=\"hljs-addition\">+       subscribe: \"HoKaufen Sie die Premium-Version f\u00fcr %{price}\",<\/span>\n    }\n}\n\nexport { translations };<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Diff<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">diff<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_41ce1ed60d3035fab5e57d856783b20a\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>Now in the <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">App.js<\/span> file, add the price parameter where we call the <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"3\">i18n.t()<\/span> method.<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"Diff\" data-shcb-language-slug=\"diff\"><span><code class=\"hljs language-diff\">\/\/ .\/App.js\n\/\/ ...\n\nexport default function App() {\n\/\/ ...\n\n  return (\n    &lt;&gt;\n      &lt;Container&gt;\n\t      \/\/ ...\n<span class=\"hljs-deletion\">-       &lt;Text&gt;{i18n.t('subscribe')}&lt;\/Text&gt;<\/span>\n<span class=\"hljs-addition\">+       &lt;Text&gt;{i18n.t('subscribe', {price : daily?.price})}&lt;\/Text&gt;<\/span>\n      &lt;\/Container&gt;\n    &lt;\/&gt;\n  );\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Diff<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">diff<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_afb69579fc541985847b6c5db52acf07\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>The application now appends the <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">price<\/span> dynamically to the <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"3\">subscribe<\/span> text defined in the <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"5\">localization.js<\/span> file.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-57214 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230506_233419_Expo-Go-1-473x1024.jpg\" alt=\"App appends price dynamically | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230506_233419_Expo-Go-1-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230506_233419_Expo-Go-1-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230506_233419_Expo-Go-1-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230506_233419_Expo-Go-1-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230506_233419_Expo-Go-1-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230506_233419_Expo-Go-1.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/p>\n<h2><span class=\"ez-toc-section\" id=\"localizing-currency\"><\/span>Localizing currency<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>As of now, we show that the subscription price is shown without the currency symbol. To provide the best user experience, it is imperative that we show the price in user\u2019s country\u2019s currency.<\/p>\n<p>\ud83d\uddd2\ufe0f Note \u00bb In a real world app, you\u2019d use a real-time currency converter to display the value in the user\u2019s currency. To focus on formatting, let\u2019s assume that the value remains the same irrespective of user\u2019s currency.<\/p>\n<p>To get the user\u2019s currency symbol, make the following changes in <code>App.js<\/code> file:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ .\/App.js<\/span>\n\n<span class=\"hljs-comment\">\/\/ ...<\/span>\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\n\t<span class=\"hljs-comment\">\/\/ ...<\/span>\n  <span class=\"hljs-keyword\">const<\/span> localProperties = Localization.getLocales()&#91;<span class=\"hljs-number\">0<\/span>]\n  <span class=\"hljs-keyword\">const<\/span> currencyCode = localProperties.currencyCode\n\t<span class=\"hljs-keyword\">const<\/span> localizedPrice = <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Intl<\/span>.NumberFormat(locale, { <span class=\"hljs-attr\">style<\/span>: <span class=\"hljs-string\">'currency'<\/span>, <span class=\"hljs-attr\">currency<\/span>: currencyCode }).format(daily?.price)\n\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;&gt;<\/span>\n\t\t\t\t\/\/ ...\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Text<\/span>&gt;<\/span>{i18n.t('subscribe', { price: localizedPrice })}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Text<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/&gt;<\/span><\/span>\n  );\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_8dac2be1247d1d607882d5c04e4492f8\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p><span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"0\">Localization.getLocales()<\/span> returns all user-defined supported locales in the order the user defined in their device settings. The locale with <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"2\">0<\/span> index is considered the one with the highest priority. The returned response will be something like this:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"> &#91;{\n    <span class=\"hljs-string\">\"languageTag\"<\/span>: <span class=\"hljs-string\">\"pl-PL\"<\/span>,\n    <span class=\"hljs-string\">\"languageCode\"<\/span>: <span class=\"hljs-string\">\"pl\"<\/span>,\n    <span class=\"hljs-string\">\"textDirection\"<\/span>: <span class=\"hljs-string\">\"ltr\"<\/span>,\n    <span class=\"hljs-string\">\"digitGroupingSeparator\"<\/span>: <span class=\"hljs-string\">\" \"<\/span>,\n    <span class=\"hljs-string\">\"decimalSeparator\"<\/span>: <span class=\"hljs-string\">\",\"<\/span>,\n    <span class=\"hljs-string\">\"measurementSystem\"<\/span>: <span class=\"hljs-string\">\"metric\"<\/span>,\n    <span class=\"hljs-string\">\"currencyCode\"<\/span>: <span class=\"hljs-string\">\"PLN\"<\/span>,\n    <span class=\"hljs-string\">\"currencySymbol\"<\/span>: <span class=\"hljs-string\">\"z\u0142\"<\/span>,\n    <span class=\"hljs-string\">\"regionCode\"<\/span>: <span class=\"hljs-string\">\"PL\"<\/span>\n  }]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_b62e38fc3a87652c6b74236b333b6134\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>We then extract the <code>currencyCode<\/code> and format it using the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Intl\/NumberFormat\">Intl.NumberFormat<\/a> object.<\/p>\n<p>Now on running the app with <code>de-DE<\/code> locale as default, you will see the formatted price with the Euro symbol and while running the app with <code>en-IN<\/code> locale, you will see the price with the Rupee symbol.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-57227 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_011217_Expo-Go-473x1024.jpg\" alt=\"Formatted price with the Euro symbol | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_011217_Expo-Go-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_011217_Expo-Go-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_011217_Expo-Go-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_011217_Expo-Go-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_011217_Expo-Go-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_011217_Expo-Go.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-57233 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_011232_Expo-Go-473x1024.jpg\" alt=\"Price with the Rupee symbol | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_011232_Expo-Go-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_011232_Expo-Go-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_011232_Expo-Go-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_011232_Expo-Go-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_011232_Expo-Go-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_011232_Expo-Go.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/p>\n<h2><span class=\"ez-toc-section\" id=\"number-formatting\"><\/span>Number formatting<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Similarly, you can also format simple numbers using <code>Intl.NumberFormat<\/code> objects**.** For example to format a number <code>123456.789<\/code>, use the following code:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> number = <span class=\"hljs-number\">123456789<\/span>;\n<span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Intl<\/span>.NumberFormat(<span class=\"hljs-string\">'de-DE'<\/span>, { <span class=\"hljs-attr\">maximumSignificantDigits<\/span>: <span class=\"hljs-number\">3<\/span> }).format(number))\n<span class=\"hljs-comment\">\/\/ Expected output: \"123.456.789\"<\/span>\n\n<span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Intl<\/span>.NumberFormat(<span class=\"hljs-string\">'en-IN'<\/span>, { <span class=\"hljs-attr\">maximumSignificantDigits<\/span>: <span class=\"hljs-number\">3<\/span> }).format(number))\n<span class=\"hljs-comment\">\/\/ Expected output: \"12,34,56,789\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_4bb6442a18c996dfe5ec1aa535cd2b03\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<h2><span class=\"ez-toc-section\" id=\"localizing-dates\"><\/span>Localizing dates<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>We will now show the user the current date in the weather app. The dates should also take the user&#8217;s locale into consideration. For example, in <code>en-IN<\/code>, May 21th, 2023 should be represented as 21\/05\/2023 in the locale\u2019s default date formatting. The default formatting for <code>de_DE<\/code> is 21.05.2023.<\/p>\n<p>To localize dates, make the following changes to <code>App.js<\/code> file:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ .\/App.js<\/span>\n\n<span class=\"hljs-comment\">\/\/ ...<\/span>\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n  <span class=\"hljs-keyword\">const<\/span> today = <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Date<\/span>()\n  <span class=\"hljs-keyword\">const<\/span> formattedDate = <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Intl<\/span>.DateTimeFormat(locale).format(today)\n\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Container<\/span>&gt;<\/span>\n\t\t      \/\/ ...\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Text<\/span>&gt;<\/span>{formattedDate}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Text<\/span>&gt;<\/span>\n        \/\/ ...\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Container<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/&gt;<\/span><\/span>\n  );\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_027fffdd696ee6a1315bd56bd61edfd5\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>If <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">today<\/span> is May 21, 2023, we see it localized as follows when we run our app.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-57241 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_014012_Expo-Go-473x1024.jpg\" alt=\"Date localized | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_014012_Expo-Go-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_014012_Expo-Go-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_014012_Expo-Go-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_014012_Expo-Go-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_014012_Expo-Go-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_014012_Expo-Go.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-57247 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_014012_Expo-Go-1-473x1024.jpg\" alt=\"Date with dashes | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_014012_Expo-Go-1-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_014012_Expo-Go-1-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_014012_Expo-Go-1-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_014012_Expo-Go-1-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_014012_Expo-Go-1-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_014012_Expo-Go-1.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/p>\n<p><span role=\"img\" aria-label=\"\ud83d\uddd2\ufe0f\">\ud83d\uddd2\ufe0f<\/span> <span class=\"notion-enable-hover\" data-token-index=\"1\">Note \u00bb You can also change the date format by passing dateStyle parameter to <\/span><span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"2\">Intl.DateTimeFormat.<\/span><\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"TypeScript\" data-shcb-language-slug=\"typescript\"><span><code class=\"hljs language-typescript\"><span class=\"hljs-comment\">\/\/ Specify date and time format using \"style\" options (i.e. full, long, medium, short)<\/span>\n<span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Intl<\/span>.DateTimeFormat(<span class=\"hljs-string\">'en-GB'<\/span>, { dateStyle: <span class=\"hljs-string\">'full'<\/span>).format(date))\n<span class=\"hljs-comment\">\/\/ Expected output: \"Sunday, 21 May, 2023 at 6:16:52 am GMT+10\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">TypeScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">typescript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_fb144b58cf73d2b6fbce3e0b40398495\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<h2><span class=\"ez-toc-section\" id=\"plurals\"><\/span>Plurals<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Handling plurals is an important aspect of internationalization. Different languages have different rules for plural forms, and it&#8217;s crucial to handle them correctly in your app.<\/p>\n<p>Now, let us add another text component under current temperature, representing maximum temperature to demonstrate this example.<\/p>\n<p>In the <code>localization.js<\/code> file, add the new key <code>temperature<\/code> and with their values in plural and singular firms.<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ .\/localization.js<\/span>\n\n<span class=\"hljs-keyword\">const<\/span> translations = {\n  <span class=\"hljs-attr\">en<\/span>: {\n    <span class=\"hljs-comment\">\/\/ ...<\/span>\n    <span class=\"hljs-attr\">temperature<\/span>: {\n      <span class=\"hljs-attr\">one<\/span>: <span class=\"hljs-string\">\"%{count} degree\"<\/span>,\n      <span class=\"hljs-attr\">other<\/span>: <span class=\"hljs-string\">\"%{count} degrees\"<\/span>,\n    },\n  },\n\n  <span class=\"hljs-attr\">de<\/span>: {\n    <span class=\"hljs-comment\">\/\/ ...<\/span>\n    <span class=\"hljs-attr\">temperature<\/span>: {\n      <span class=\"hljs-attr\">one<\/span>: <span class=\"hljs-string\">\"%{count} grad\"<\/span>,\n      <span class=\"hljs-attr\">other<\/span>: <span class=\"hljs-string\">\"%{count} grade\"<\/span>,\n    },\n  },\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_430a350c1c6ba925f620e24fa0beb3d5\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>In the <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">App.js<\/span> file, make the following changes:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ .\/App.js<\/span>\n<span class=\"hljs-comment\">\/\/ ...<\/span>\n\n<span class=\"hljs-keyword\">const<\/span> dailyWeatherMock = {\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n  <span class=\"hljs-attr\">maxInCelsius<\/span>: <span class=\"hljs-number\">9.2<\/span>,\n  <span class=\"hljs-comment\">\/\/ ... <\/span>\n}\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> daily = dailyWeatherMock;\n  <span class=\"hljs-keyword\">const<\/span> i18n = <span class=\"hljs-keyword\">new<\/span> I18n(translations)\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Container<\/span>&gt;<\/span>\n\t\t\t\t\t\/\/ ...\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Text<\/span>&gt;<\/span>{i18n.t(\"temperature\", {count: daily.maxInCelsius})}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Text<\/span>&gt;<\/span>\n\t        \/\/ ...\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Container<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/&gt;<\/span><\/span>\n  );\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_dc8dbaabec1e12ce195cf7e96e676a0a\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>Upon running the app, you will notice that plurals are now being considered while localizing Strings. When the value is <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">1<\/span>, the max temperature is rendered as \u201c1 degree\u201d.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-57253 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230507_020450_Expo-Go-1-473x1024.jpg\" alt=\"Localize temperature | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230507_020450_Expo-Go-1-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230507_020450_Expo-Go-1-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230507_020450_Expo-Go-1-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230507_020450_Expo-Go-1-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230507_020450_Expo-Go-1-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230507_020450_Expo-Go-1.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/p>\n<p>For a zero value, we get \u201c0 degrees\u201d. Similarly, for a value of <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">15<\/span>, we get \u201c15 degrees.\u201d<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-57259 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230507_020022_Expo-Go-1-473x1024.jpg\" alt=\"O degrees displayed as a plural | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230507_020022_Expo-Go-1-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230507_020022_Expo-Go-1-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230507_020022_Expo-Go-1-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230507_020022_Expo-Go-1-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230507_020022_Expo-Go-1-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230507_020022_Expo-Go-1.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/p>\n<h3><span class=\"ez-toc-section\" id=\"complex-plurals\"><\/span>Complex plurals<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Languages can have many <a href=\"https:\/\/www.unicode.org\/cldr\/charts\/43\/supplemental\/language_plural_rules.html\">forms of plurals<\/a>. In English, we have a simple distinction between the singular form &#8220;book&#8221; and the plural form &#8220;books.&#8221; The plural form is used for any count other than 1.<\/p>\n<table style=\"border-collapse: collapse; width: 100%;\">\n<thead>\n<tr>\n<td style=\"width: 50%;\">English<\/td>\n<td style=\"width: 50%;\">Russian<\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"width: 50%;\">0 books<\/td>\n<td style=\"width: 50%;\">0 \u043a\u043d\u0438\u0433 (knig)<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">1 book<\/td>\n<td style=\"width: 50%;\">1 \u043a\u043d\u0438\u0433\u0430 (knigi)<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">2 books<\/td>\n<td style=\"width: 50%;\">2 \u043a\u043d\u0438\u0433\u0438 (knigi)<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">3 books<\/td>\n<td style=\"width: 50%;\">3 \u043a\u043d\u0438\u0433\u0438 (knigi)<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">4 books<\/td>\n<td style=\"width: 50%;\">4 \u043a\u043d\u0438\u0433\u0438 (knigi)<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">5 books<\/td>\n<td style=\"width: 50%;\">5\u00a0\u043a\u043d\u0438\u0433 (knig)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In Russian, the plural forms are more complex. The word for &#8220;book&#8221; in the singular form is &#8220;\u043a\u043d\u0438\u0433\u0430&#8221; (kniga). However, the plural form has different variations depending on the count. For counts ending in 2, 3, or 4 (except those ending in 12, 13, or 14), the word &#8220;\u043a\u043d\u0438\u0433\u0438&#8221; (knigi) is used. For any other count, including 0, 1, and numbers ending in 0 or those ending in 5-9, the word &#8220;\u043a\u043d\u0438\u0433&#8221; (knig) is used.<\/p>\n<p>\ud83d\uddd2\ufe0f Note \u00bb The default keywords for pluralisation offered by i18n-js library are\u00a0<code>zero<\/code>,\u00a0<code>one<\/code>, and\u00a0<code>other<\/code> which isn\u2019t sufficient to include all types of plurals. Here\u2019s an example that uses complex plurals for Russian.<\/p>\n<h3><\/h3>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">npm install make-plural<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_0ad4f4721ad40714c288c01359424cf9\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>You can now specify additional categories for plurals now.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-57368\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot-2023-05-21-at-11.10.23-PM-1024x102.png\" alt=\"Plural rules for various languages | Phrase\" width=\"1024\" height=\"102\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot-2023-05-21-at-11.10.23-PM-1024x102.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot-2023-05-21-at-11.10.23-PM-300x30.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot-2023-05-21-at-11.10.23-PM-768x77.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot-2023-05-21-at-11.10.23-PM.png 1102w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>Resource: You can find plural rules for various languages <a href=\"http:\/\/www.unicode.org\/cldr\/cldr-aux\/charts\/22\/supplemental\/language_plural_rules.html\">here<\/a>.<\/p>\n<p>Now in the <code>localization.js<\/code> file, you can define the translations for all plural categories.<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> translations = {\n  <span class=\"hljs-attr\">en<\/span>: {\n    <span class=\"hljs-attr\">steps<\/span>: {\n      <span class=\"hljs-attr\">one<\/span>: <span class=\"hljs-string\">\"%{count} book\"<\/span>,\n      <span class=\"hljs-attr\">other<\/span>: <span class=\"hljs-string\">\"%{count} books\"<\/span>,\n    },\n  },\n  <span class=\"hljs-attr\">ru<\/span>: {\n    <span class=\"hljs-attr\">steps<\/span>: {\n      <span class=\"hljs-attr\">one<\/span>: <span class=\"hljs-string\">\"%{count} \u043a\u043d\u0438\u0433\u0430\"<\/span>,\n      <span class=\"hljs-attr\">few<\/span>: <span class=\"hljs-string\">\"%{count} \u043a\u043d\u0438\u0433\u0438\"<\/span>,\n      <span class=\"hljs-attr\">many<\/span>: <span class=\"hljs-string\">\"%{count} \u043a\u043d\u0438\u0433\"<\/span>,\n      <span class=\"hljs-attr\">other<\/span>: <span class=\"hljs-string\">\"%{count} \u043a\u043d\u0438\u0433\"<\/span>,\n    },\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_83c221e88093fcde6bc3f02ccd6a7e7b\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>Now in the <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">App.js<\/span> file<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> { I18n } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'i18n-js'<\/span>\n<span class=\"hljs-keyword\">import<\/span> { translations } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'.\/localization'<\/span>\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'intl-pluralrules'<\/span>\n<span class=\"hljs-keyword\">import<\/span> { useMakePlural } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"i18n-js\"<\/span>\n<span class=\"hljs-keyword\">import<\/span> * <span class=\"hljs-keyword\">as<\/span> Localization <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'expo-localization'<\/span>\n<span class=\"hljs-keyword\">import<\/span> { ru } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"make-plural\"<\/span>\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\n  <span class=\"hljs-keyword\">const<\/span> i18n = <span class=\"hljs-keyword\">new<\/span> I18n(translations)\n  i18n.locale = <span class=\"hljs-string\">\"ru\"<\/span>\n  i18n.enableFallback = <span class=\"hljs-literal\">true<\/span>\n  i18n.defaultLocale = <span class=\"hljs-string\">\"en\"<\/span>\n\n\ti18n.pluralization.register(<span class=\"hljs-string\">\"ru\"<\/span>, useMakePlural({ <span class=\"hljs-attr\">pluralizer<\/span>: ru }))\n\n  <span class=\"hljs-built_in\">console<\/span>.log(i18n.t(<span class=\"hljs-string\">'steps'<\/span>, { <span class=\"hljs-attr\">count<\/span>: <span class=\"hljs-number\">0<\/span> })) <span class=\"hljs-comment\">\/\/0 \u043a\u043d\u0438\u0433<\/span>\n  <span class=\"hljs-built_in\">console<\/span>.log(i18n.t(<span class=\"hljs-string\">'steps'<\/span>, { <span class=\"hljs-attr\">count<\/span>: <span class=\"hljs-number\">1<\/span> })) <span class=\"hljs-comment\">\/\/1 \u043a\u043d\u0438\u0433\u0430<\/span>\n  <span class=\"hljs-built_in\">console<\/span>.log(i18n.t(<span class=\"hljs-string\">'steps'<\/span>, { <span class=\"hljs-attr\">count<\/span>: <span class=\"hljs-number\">2<\/span> })) <span class=\"hljs-comment\">\/\/2 \u043a\u043d\u0438\u0433\u0438<\/span>\n  <span class=\"hljs-built_in\">console<\/span>.log(i18n.t(<span class=\"hljs-string\">'steps'<\/span>, { <span class=\"hljs-attr\">count<\/span>: <span class=\"hljs-number\">3<\/span> })) <span class=\"hljs-comment\">\/\/3 \u043a\u043d\u0438\u0433\u0438<\/span>\n  <span class=\"hljs-built_in\">console<\/span>.log(i18n.t(<span class=\"hljs-string\">'steps'<\/span>, { <span class=\"hljs-attr\">count<\/span>: <span class=\"hljs-number\">4<\/span> })) <span class=\"hljs-comment\">\/\/4 \u043a\u043d\u0438\u0433\u0438<\/span>\n  <span class=\"hljs-built_in\">console<\/span>.log(i18n.t(<span class=\"hljs-string\">'steps'<\/span>, { <span class=\"hljs-attr\">count<\/span>: <span class=\"hljs-number\">5<\/span> })) <span class=\"hljs-comment\">\/\/5 \u043a\u043d\u0438\u0433<\/span>\n  <span class=\"hljs-built_in\">console<\/span>.log(i18n.t(<span class=\"hljs-string\">'steps'<\/span>, { <span class=\"hljs-attr\">count<\/span>: <span class=\"hljs-number\">6<\/span> })) <span class=\"hljs-comment\">\/\/6 \u043a\u043d\u0438\u0433<\/span>\n  <span class=\"hljs-built_in\">console<\/span>.log(i18n.t(<span class=\"hljs-string\">'steps'<\/span>, { <span class=\"hljs-attr\">count<\/span>: <span class=\"hljs-number\">7<\/span> })) <span class=\"hljs-comment\">\/\/7 \u043a\u043d\u0438\u0433<\/span>\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_afffb1c589020edc8cc1de8093deb7b1\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<h2><span class=\"ez-toc-section\" id=\"localizing-measurement\"><\/span>Localizing measurement<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Currently the app doesn\u2019t respect user\u2019s preferred measurement system (<a href=\"https:\/\/en.wikipedia.org\/wiki\/System_of_measurement#Metric_system\">metric<\/a> or <a href=\"https:\/\/en.wikipedia.org\/wiki\/System_of_measurement#Imperial_and_US_customary_units\">imperial<\/a>), which is based on the device\u2019s locale. We will now display the current temperature in user\u2019s preferred measurement system.<\/p>\n<p>Make the following changes in <code>localization.js<\/code> file:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ .\/localization.js<\/span>\n\n<span class=\"hljs-keyword\">const<\/span> translations = {\n    <span class=\"hljs-attr\">en<\/span>: {\n\t      <span class=\"hljs-comment\">\/\/ ...<\/span>\n\t\t\t\t<span class=\"hljs-comment\">\/\/ we will use Celsius for metric system<\/span>\n        <span class=\"hljs-attr\">current_temp_in_celsius<\/span>: <span class=\"hljs-string\">\"%{degree}\u00b0C\"<\/span>,\n\t\t\t\t<span class=\"hljs-comment\">\/\/ we will use Fahrenheit for imperial system<\/span>\n        <span class=\"hljs-attr\">current_temp_in_fahrenheit<\/span>: <span class=\"hljs-string\">\"%{degree}\u00b0F\"<\/span>,\n    },\n\t\t<span class=\"hljs-attr\">ar<\/span>: {\n\t\t\t\t<span class=\"hljs-comment\">\/\/ ..<\/span>\n\t\t    <span class=\"hljs-attr\">current_temp_in_celsius<\/span>: <span class=\"hljs-string\">\"\u062f\u0631\u062c\u0629 \u0645\u0626\u0648\u064a\u0629 %{degree}\"<\/span>,\n\t\t    <span class=\"hljs-attr\">current_temp_in_fahrenheit<\/span>: <span class=\"hljs-string\">\"\u062f\u0631\u062c\u0629 \u0641\u0647\u0631\u0646\u0647\u0627\u064a\u062a %{degree}\"<\/span>,\n  },\n\t<span class=\"hljs-comment\">\/\/ ...<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_ba085c9e4398b3bf548313b6276fd1b2\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>\ud83d\uddd2\ufe0f Note \u00bb We do not add translations for any other languages because in most languages the temperature Units are represented in \u00b0C or \u00b0F which we defines for <code>en<\/code> language (which is our fallback language).<\/p>\n<p>In the <code>App.js<\/code> file, make the following changes:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ .\/App.js<\/span>\n\n<span class=\"hljs-comment\">\/\/...<\/span>\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\n  <span class=\"hljs-keyword\">let<\/span> &#91;locale, setLocale] = useState(Localization.locale);\n\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n  <span class=\"hljs-keyword\">let<\/span> { measurementSystem } = Localization.getLocales()&#91;<span class=\"hljs-number\">0<\/span>]\n\n  <span class=\"hljs-keyword\">let<\/span> currentTemperature =\n    measurementSystem === <span class=\"hljs-string\">\"metric\"<\/span>\n    ? i18n.t(<span class=\"hljs-string\">\"current_temp_in_celsius\"<\/span>, { <span class=\"hljs-attr\">degree<\/span>: daily.currentInCelsius })\n    : i18n.t(<span class=\"hljs-string\">\"current_temp_in_fahrenheit\"<\/span>, { <span class=\"hljs-attr\">degree<\/span>: daily.currentInFahrenheit })\n\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Container<\/span>&gt;<\/span>\n\t\t\t\t\t\/\/ ...\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Text<\/span>&gt;<\/span>{currentTemperature}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Text<\/span>&gt;<\/span>\n\t\t\t\t\t\/\/ ...\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Container<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/&gt;<\/span><\/span>\n  );\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_7b7d68d77c1bc848b0fe71695b78fdaf\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>Upon running the app with the device locale set to <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">en-US<\/span>, the current temperature will be shown in degrees Fahrenheit (F):<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-57383 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_015517_Expo-Go-473x1024.jpg\" alt=\"Temperature will be shown in degrees Fahrenheit (F) | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_015517_Expo-Go-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_015517_Expo-Go-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_015517_Expo-Go-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_015517_Expo-Go-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_015517_Expo-Go-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_015517_Expo-Go.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/p>\n<p>While running the app with <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">en-IN<\/span> or <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"3\">de-DE <\/span>as default locale, the current temperature will be shown in degree Celsius (C).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-57389 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_015603_Expo-Go-473x1024.jpg\" alt=\"Temperature will be shown in degree Celsius (C) | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_015603_Expo-Go-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_015603_Expo-Go-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_015603_Expo-Go-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_015603_Expo-Go-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_015603_Expo-Go-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230521_015603_Expo-Go.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/p>\n<h3><span class=\"ez-toc-section\" id=\"change-language-from-within-the-application\"><\/span><strong>Change Language from within the Application<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>As of now, the only way for a user to change the language of the app is by using their system settings. We will now add a feature to toggle supported languages from within the app.<\/p>\n<p>In the <code>App.js<\/code> file, make the following settings<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ .\/App.js<\/span>\n\n<span class=\"hljs-keyword\">import<\/span> React, { useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { Text, Button } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'react-native'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> * <span class=\"hljs-keyword\">as<\/span> Localization <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'expo-localization'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { I18n } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'i18n-js'<\/span>\n<span class=\"hljs-keyword\">import<\/span> { translations } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'.\/localization'<\/span>;\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\t<span class=\"hljs-comment\">\/\/ By default pick the locale from System settings<\/span>\n  <span class=\"hljs-keyword\">let<\/span> &#91;locale, setLocale] = useState(Localization.locale);\n  <span class=\"hljs-keyword\">const<\/span> daily = dailyWeatherMock;\n  <span class=\"hljs-keyword\">const<\/span> i18n = <span class=\"hljs-keyword\">new<\/span> I18n(translations)\n  i18n.locale = locale\n  i18n.enableFallback = <span class=\"hljs-literal\">true<\/span>\n  i18n.defaultLocale = <span class=\"hljs-string\">\"en\"<\/span>;\n\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;&gt;<\/span>\n\t\t    \/\/ ...\n           <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Button<\/span> <span class=\"hljs-attr\">onPress<\/span>=<span class=\"hljs-string\">{()<\/span> =&gt;<\/span> setLocale(\"en\")} title=\"English\" color=\"#841584\" \/&gt;\n           <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Button<\/span> <span class=\"hljs-attr\">onPress<\/span>=<span class=\"hljs-string\">{()<\/span> =&gt;<\/span> setLocale(\"de\")} title=\"German\" color=\"#841584\" \/&gt;\n    <span class=\"hljs-tag\">&lt;\/&gt;<\/span><\/span>\n  );\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_010c1df7d80b2ba51009720222af471f\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>When the button is pressed, we change the locale using the <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">setLocale()<\/span> method passing in the <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"3\">Locale<\/span> param.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-57399 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/device-2023-05-07-022926.gif\" alt=\"Button pressed to change the locale | Phrase\" width=\"473\" height=\"1025\" \/><\/p>\n<h2><span class=\"ez-toc-section\" id=\"adding-right-to-left-support\"><\/span>Adding right-to-left support<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Languages that use scripts like Arabic, Hebrew, Farsi, and Urdu are written from right to left (RTL), while languages like English, French, and Spanish are written from left to right (LTR). Let\u2019s accommodate RTL languages in our app.<\/p>\n<p>To demonstrate the change in layout direction, we will add a title \u201cThe Weather App\u201d on the top left of the app for LTR languages and on top right for RTL languages.<\/p>\n<p>Make the following changes to <code>App.js<\/code> file:<\/p>\n<p>Go to <code>app.json<\/code> file and make the following changes:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"JSON \/ JSON with Comments\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json\"><span class=\"hljs-comment\">\/\/ app.json<\/span>\n\n{\n  <span class=\"hljs-attr\">\"expo\"<\/span>: {\n    <span class=\"hljs-attr\">\"extra\"<\/span>: {\n      <span class=\"hljs-attr\">\"supportsRTL\"<\/span>: <span class=\"hljs-literal\">true<\/span>\n    },\n    <span class=\"hljs-attr\">\"plugins\"<\/span>: &#91;<span class=\"hljs-string\">\"expo-localization\"<\/span>],\n\t\t<span class=\"hljs-comment\">\/\/ ...<\/span>\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON with Comments<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">json<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_61daa28d0241af6aac6c0f8414fceefd\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>In the <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">localization.js<\/span> file, add a new language locale <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"3\">ur<\/span>(Urdu) and make the following changes:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ \/localization.js<\/span>\n\n<span class=\"hljs-keyword\">const<\/span> translations = {\n  <span class=\"hljs-attr\">en<\/span>: {\n    <span class=\"hljs-attr\">greeting<\/span>: <span class=\"hljs-string\">\"Hello\"<\/span>,\n    <span class=\"hljs-attr\">app_title<\/span>: <span class=\"hljs-string\">\"The Weather App\"<\/span>,\n\t\t<span class=\"hljs-comment\">\/\/ ...<\/span>\n  },\n  <span class=\"hljs-attr\">ur<\/span>: {\n    <span class=\"hljs-attr\">greeting<\/span>: <span class=\"hljs-string\">\"\u06c1\u06cc\u0644\u0648\"<\/span>,\n    <span class=\"hljs-attr\">app_title<\/span>: <span class=\"hljs-string\">\"\u0645\u0648\u0633\u0645 \u06a9\u06cc \u0627\u06cc\u067e\"<\/span>,\n\t\t<span class=\"hljs-comment\">\/\/ ...<\/span>\n  },<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_4e47f9a4b58921a933a9218922177796\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>Now in the <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">App.js<\/span> file, make the following changes:<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ .\/App.js<\/span>\n\n<span class=\"hljs-keyword\">import<\/span> React, { useEffect, useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>\n<span class=\"hljs-keyword\">import<\/span> { Text, View, Button, I18nManager } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'react-native'<\/span>\n<span class=\"hljs-keyword\">import<\/span> * <span class=\"hljs-keyword\">as<\/span> Localization <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'expo-localization'<\/span>\n<span class=\"hljs-keyword\">import<\/span> { I18n } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'i18n-js'<\/span>\n<span class=\"hljs-keyword\">import<\/span> { translations } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'.\/localization'<\/span>\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\t<span class=\"hljs-comment\">\/\/...<\/span>\n\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">View<\/span> <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{styles.container}<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">View<\/span> <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{styles.title}<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Text<\/span>&gt;<\/span>{i18n.t('app_title')}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Text<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">View<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">View<\/span>&gt;<\/span>\n\t\t\t\/\/ ...\n    <span class=\"hljs-tag\">&lt;\/&gt;<\/span><\/span>\n  )\n}\n\n<span class=\"hljs-keyword\">const<\/span> styles = StyleSheet.create({\n  <span class=\"hljs-attr\">container<\/span>: {\n    <span class=\"hljs-attr\">paddingTop<\/span>: <span class=\"hljs-number\">30<\/span>,\n    <span class=\"hljs-attr\">padding<\/span>: <span class=\"hljs-number\">0<\/span>,\n    <span class=\"hljs-attr\">backgroundColor<\/span>: <span class=\"hljs-string\">'pink'<\/span>,\n  },\n  <span class=\"hljs-attr\">title<\/span>: {\n    <span class=\"hljs-attr\">fontSize<\/span>: <span class=\"hljs-number\">35<\/span>,\n    <span class=\"hljs-attr\">paddingVertical<\/span>: <span class=\"hljs-number\">5<\/span>,\n    <span class=\"hljs-attr\">height<\/span>: <span class=\"hljs-number\">40<\/span>,\n    <span class=\"hljs-attr\">width<\/span>: <span class=\"hljs-string\">'100%'<\/span>,\n    \n    <span class=\"hljs-comment\">\/\/ \ud83d\udc47 Using \"start\" rules instead of \"left\" and<\/span>\n    <span class=\"hljs-comment\">\/\/    and \"right\" makes the layout adapt to RTL<\/span>\n    <span class=\"hljs-attr\">marginStart<\/span>: <span class=\"hljs-number\">20<\/span>,\n    <span class=\"hljs-attr\">alignItems<\/span>: <span class=\"hljs-string\">'flex-start'<\/span>\n  },\n})<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div id=\"acf\/text-block_4fd2738f48dda75757f7c11a51f6d5a1\" class=\"pxblock pxblock--text spacing--default bg--white\">\n\n\t\n\t<div class=\"container\">\n\t\t<div class=\"wysiwyg animate-in\">\n\t\t\t<p>On running the app with locale <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">en-IN<\/span>, you will see the following screen. The title \u201cThe Weather App\u201d is displayed on the top left.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-57408 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230522_010731_Expo-Go-473x1024.jpg\" alt=\"The Weather App displayed on the top left | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230522_010731_Expo-Go-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230522_010731_Expo-Go-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230522_010731_Expo-Go-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230522_010731_Expo-Go-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230522_010731_Expo-Go-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230522_010731_Expo-Go.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/p>\n<p>On running the app with locale <span class=\"notion-enable-hover\" spellcheck=\"false\" data-token-index=\"1\">ur-IN<\/span>, you see the following screen. The title \u201cThe Weather App\u201d is displayed on the top right since Urdu is RTL language so the screen layout is mirrored.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-57414 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230522_011121_Expo-Go-473x1024.jpg\" alt=\"The app title in Urdu | Phrase\" width=\"473\" height=\"1024\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230522_011121_Expo-Go-473x1024.jpg 473w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230522_011121_Expo-Go-138x300.jpg 138w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230522_011121_Expo-Go-768x1664.jpg 768w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230522_011121_Expo-Go-709x1536.jpg 709w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230522_011121_Expo-Go-945x2048.jpg 945w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/07\/Screenshot_20230522_011121_Expo-Go.jpg 1080w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/p>\n<p>\ud83d\uddd2\ufe0f Note \u00bb To style the View we used <code>maginStart<\/code> and <code>flex-start<\/code> styling which respects the current layout direction i.e when the language is LTR, the margin is from the left end and the title is aligned towards the left end too. But when the language is RTL, everything is aligned from the right end. Using<code>marginLeft<\/code> and <code>marginRight<\/code>instead will not respect the layout direction.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"wrapping-up-our-react-native-localization-guide\"><\/span>Wrapping up our React Native localization guide<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>In this article, we discussed the importance of internationalisation and localization in a React Native weather app. We used the i18n-js and Expo Localization libraries to localize the app&#8217;s text content, date format, and temperature units. Overall, internationalising and localizing a React Native app can be challenging, but the i18n-js and Expo Localization libraries provide useful tools to make the process easier. By following the steps outlined in this article, you can create a more inclusive and user-friendly app that can appeal to a wider audience.<\/p>\n<p>You can find the final project on <a href=\"https:\/\/github.com\/PhraseApp-Blog\/React-native-i18n\">GitHub<\/a>.<\/p>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to make the most of React Native localization using the Expo framework and create an inclusive, user-friendly app with a global appeal.<\/p>\n","protected":false},"author":41,"featured_media":39386,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_stopmodifiedupdate":true,"_modified_date":"","_searchwp_excluded":"","footnotes":""},"categories":[40],"class_list":["post-8721","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-software-localization"],"acf":[],"_links":{"self":[{"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/posts\/8721"}],"collection":[{"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/comments?post=8721"}],"version-history":[{"count":14,"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/posts\/8721\/revisions"}],"predecessor-version":[{"id":83790,"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/posts\/8721\/revisions\/83790"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/media\/39386"}],"wp:attachment":[{"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/media?parent=8721"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/phrase.com\/wp-json\/wp\/v2\/categories?post=8721"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}