How to i18n in Flutter?
Tags: flutter, dart, internationalization
Published: 2019-07-17 21:31:22

---
title: "How to i18n in Flutter?"
published: true
description: In this post we will discus about i18n and see two options to handle i18n in our projects.
tags: flutter, dart, internationalization
cover_image: https://blog.apiki.com/wp-content/uploads/sites/2/2015/08/internacionalizacao-de-temas-e-plugins-wordpress.png
---

###UPDATE: 
**The plugin used in this article was deprecated, Use it at your own risk.**



<p name="5691" id="5691" class="graf graf--p graf-after--h3">After some months (maybe a year) working with Flutter I want to start sharing advanced things about Flutter like state management, i18n and more. Also checkout my <a href="https://www.youtube.com/channel/UCBiJzXGvkuT9aG2Yq8BYYnQ/videos" data-href="https://www.youtube.com/channel/UCBiJzXGvkuT9aG2Yq8BYYnQ/videos" class="markup--anchor markup--p-anchor" rel="noopener" target="_blank">Youtube channel</a> for videos about Flutter.</p><p name="f4b1" id="f4b1" class="graf graf--p graf-after--p">In this post we will discus about i18n and see two options to handle i18n in our projects.</p><h3 name="404b" id="404b" class="graf graf--h3 graf-after--p">What is i18n?</h3><p name="3680" id="3680" class="graf graf--p graf-after--h3">Is a shorthand for <strong class="markup--strong markup--p-strong">internationalization. </strong>The came because the internationalization word have twenty letters and between the first letter (<strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">i</em></strong>) and the last(<strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">n</em></strong>) there are eighteen letters.</p><blockquote name="9500" id="9500" class="graf graf--blockquote graf-after--p"><strong class="markup--strong markup--blockquote-strong">Internationalization</strong> means making our app available in other language, country or locale.</blockquote><h3 name="c901" id="c901" class="graf graf--h3 graf-after--blockquote"><strong class="markup--strong markup--h3-strong">How do we setup i18n in Flutter?</strong></h3><p name="62c9" id="62c9" class="graf graf--p graf-after--h3">I know two ways to do i18n in Flutter, just keep reading…</p><h3 name="495f" id="495f" class="graf graf--h3 graf-after--p">1. The common way: manually</h3><p name="a1ed" id="a1ed" class="graf graf--p graf-after--h3">Here maybe you want to pause my post and take a look to the Flutter documentation, to get some background. Basically you will need to:</p><ol class="postList"><li name="824a" id="824a" class="graf graf--li graf-after--p">Create a single-source class that will have your strings<br>The class that you will use to access your strings. It uses the Intl package to pick your strings or you can choose your own approach.</li><li name="e537" id="e537" class="graf graf--li graf-after--li">Create a class for each supported locale by your app<strong class="markup--strong markup--li-strong"> </strong>😔<strong class="markup--strong markup--li-strong"><br></strong>You also need to create a single file for each locale supported by your app. Each file will have texts localized for that locale.</li><li name="13d6" id="13d6" class="graf graf--li graf-after--li">Configure your MaterialApp with <strong class="markup--strong markup--li-strong">localizationsDelegates </strong>to point your custom localization delegates (this allow you to access the strings).</li></ol><p name="46eb" id="46eb" class="graf graf--p graf-after--li">The you will use something like that to access your strings:</p><pre name="558b" id="558b" class="graf graf--pre graf-after--p"><strong class="markup--strong markup--pre-strong">MyLocalizations</strong>.of(<strong class="markup--strong markup--pre-strong">context</strong>).appDescription</pre><h4 name="4b4e" id="4b4e" class="graf graf--h4 graf-after--pre">What is wrong with this method?</h4><p name="6fb9" id="6fb9" class="graf graf--p graf-after--h4">Nothing wrong here, we just have some negative points…</p><ul class="postList"><li name="32af" id="32af" class="graf graf--li graf-after--p">Hard to set it up. You must create the classes containing your translated strings.</li><li name="83c7" id="83c7" class="graf graf--li graf-after--li">Hard to translate your strings😪.</li><li name="3c9c" id="3c9c" class="graf graf--li graf-after--li">Each time you want to add a new string you will need to add it in each locale’s strings file😔.</li><li name="e850" id="e850" class="graf graf--li graf-after--li">IntelliJ can not tell you whether your strings key already exists or it is wrong, and you can get runtime error (or even crash).</li></ul><p name="c17b" id="c17b" class="graf graf--p graf-after--li">This is great for small projects (maybe not). If you have a big project that support, lets say, more than two locales you will need to create files for each locale and add the strings manually. It will be very hard to translate your strings.</p><h3 name="abb6" id="abb6" class="graf graf--h3 graf-after--p">2. Automated way: <strong class="markup--strong markup--h3-strong">Flutter i18n p</strong>lugin</h3><p name="567b" id="567b" class="graf graf--p graf-after--h3">Let me introduce to you the <strong class="markup--strong markup--p-strong">Flutter i18n </strong>Plugin<strong class="markup--strong markup--p-strong"> </strong>for <strong class="markup--strong markup--p-strong">IntelliJ IDEA </strong>created by <a href="https://github.com/long1eu" data-href="https://github.com/long1eu" class="markup--anchor markup--p-anchor" rel="noopener" target="_blank">Razvan Lung</a>. A plugin that simplify i18n managment in your project.</p><p name="c182" id="c182" class="graf graf--p graf-after--p">What are the advantages of this plugin over the default implementation?</p><ul class="postList"><li name="9dbc" id="9dbc" class="graf graf--li graf-after--p">Easy implementation;</li><li name="6b80" id="6b80" class="graf graf--li graf-after--li">Easy to translate your strings because it uses <strong class="markup--strong markup--li-strong">.arb</strong> files;</li><li name="87c8" id="87c8" class="graf graf--li graf-after--li">IntelliJ will let you know wether your string’s key is wrong or duplicated at develompent time.</li></ul><figure name="3987" id="3987" class="graf graf--figure graf-after--li"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 349px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 49.8%;"></div><img class="graf-image" data-image-id="1*-SQeUn7Z1f7VRhirFmRo4w.png" data-width="1256" data-height="626" src="https://cdn-images-1.medium.com/max/800/1*-SQeUn7Z1f7VRhirFmRo4w.png"></div></figure><p name="b9f2" id="b9f2" class="graf graf--p graf-after--figure"><strong class="markup--strong markup--p-strong">.arb </strong>(Android Resources Bundle) are files supported by the <strong class="markup--strong markup--p-strong">Intl </strong>Dart’s package, also supporteb by the Google translator toolkit. Each locale have it own .arb file containing JSON table with strings for that locale.</p><h3 name="98f3" id="98f3" class="graf graf--h3 graf-after--p"><strong class="markup--strong markup--h3-strong">How do I set it up?</strong></h3><ol class="postList"><li name="fdee" id="fdee" class="graf graf--li graf-after--h3"><strong class="markup--strong markup--li-strong">Getting the plugin<br></strong>On IntelliJ IDEA go to <strong class="markup--strong markup--li-strong">Settings &gt; Plugins </strong>and search for <strong class="markup--strong markup--li-strong">Flutter i18n </strong>and click on install. Once the download completes restart your IDE.</li></ol><figure name="3071" id="3071" class="graf graf--figure graf-after--li"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 364px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 51.9%;"></div><img class="graf-image" data-image-id="1*CK5CDqckx0hajL733egQ1Q.gif" data-width="1748" data-height="908" src="https://miro.medium.com/max/1050/1*CK5CDqckx0hajL733egQ1Q.gif"></div>
2. <strong class="markup--strong markup--p-strong">The next step</strong> is to update our <strong class="markup--strong markup--p-strong">MaterialApp </strong>widget and add the generated localization delegate to give us the the access of our strings over all of our widgets and the generated supported locales list that is basically contains the locale code of each generated <strong class="markup--strong markup--p-strong">.arb </strong>locale’s file.</p><pre name="861d" id="861d" class="graf graf--pre graf-after--p">class <strong class="markup--strong markup--pre-strong">MyApp </strong>extends <strong class="markup--strong markup--pre-strong">StatelessWidget </strong>{<br>  <br>  @override<br>  <strong class="markup--strong markup--pre-strong">Widget </strong>build(BuildContext context) {<br>    return <strong class="markup--strong markup--pre-strong">MaterialApp</strong>(<br>      title: &#39;My App&#39;,<br>      <strong class="markup--strong markup--pre-strong">localizationsDelegates: [S.<em class="markup--em markup--pre-em">delegate</em>]</strong>,<br>      <strong class="markup--strong markup--pre-strong">supportedLocales: S.<em class="markup--em markup--pre-em">delegate</em>.supportedLocales</strong>,<br>      <em class="markup--em markup--pre-em">//localeResolutionCallback:</em> ,<br>      home: HomePage(),<br>    );<br>  }<br>}</pre><p name="2e9c" id="2e9c" class="graf graf--p graf-after--pre">The plugin generate a class called <strong class="markup--strong markup--p-strong">S </strong>this is the class that you use to get your strings providing the context into it. You get your strings by calling: <code class="markup--code markup--p-code">S.of(context).yourStringKey</code>.</p><p name="0eda" id="0eda" class="graf graf--p graf-after--p">Note: we also have the option to register a <strong class="markup--strong markup--p-strong">resolution callback </strong>(the callback called if user select an unsupported locale), here we basicaly should choose wich locale will be the default in case of an unsupported locale get selected. If we do not provide a resolution callback the plugin will choose the first supported locale or we can provide a custom one…</p><pre name="26e8" id="26e8" class="graf graf--pre graf-after--p">// use English as the default locale<br>localeResolutionCallback: <strong class="markup--strong markup--pre-strong">S.<em class="markup--em markup--pre-em">delegate</em>.resolution(fallback: Locale(&#39;en&#39;))</strong></pre><h3 name="8c07" id="8c07" class="graf graf--h3 graf-after--pre">Adding new arb files manually</h3><p name="46bf" id="46bf" class="graf graf--p graf-after--h3">The plugin create a default .arb file for English. To add a new arb file right click on <strong class="markup--strong markup--p-strong">root-project/res</strong> folder and select <strong class="markup--strong markup--p-strong">New</strong> -&gt;<strong class="markup--strong markup--p-strong"> Arb File</strong>. Then pick your language from the list, and region if necessary.Your arb files are located at “<strong class="markup--strong markup--p-strong">root-project/res/values/”.</strong></p><figure name="ac2b" id="ac2b" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 513px; max-height: 431px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 84%;"></div><img class="graf-image" data-image-id="1*r_hUhFOCrsUy74ry-2e0Rw.png" data-width="513" data-height="431" src="https://cdn-images-1.medium.com/max/800/1*r_hUhFOCrsUy74ry-2e0Rw.png"></div></figure><h4 name="f2e1" id="f2e1" class="graf graf--h4 graf-after--figure">1. Referencing the values</h4><p name="7b06" id="7b06" class="graf graf--p graf-after--h4">The arb JSON table’s keys, become a valid Dart variable names. They correspond to methods from the <strong class="markup--strong markup--p-strong">S</strong> class. For example:</p><p name="42ff" id="42ff" class="graf graf--p graf-after--p"><code class="markup--code markup--p-code">S.of(context).how_to_play</code></p><p name="7877" id="7877" class="graf graf--p graf-after--p">Those Dart variable names are also generated when you extract a string. In case the user change the device language the (<strong class="markup--strong markup--p-strong">S</strong>) class automatically load values for the new locale (You don’t need to restart).</p><h4 name="ca79" id="ca79" class="graf graf--h4 graf-after--p">Adding new .arb files and register the strings automatically</h4><p name="615a" id="615a" class="graf graf--p graf-after--h4">To create the .arb file for Portuguese for example, you can just got to a string and press <strong class="markup--strong markup--p-strong">Alt+Enter </strong>you have the option to automatically internationalize that string. And if the arb file for that locale does not exist, you can easylly creat it. See with your own eyes…</p><figure name="8938" id="8938" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 397px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 56.699999999999996%;"></div><img class="graf-image" data-image-id="1*fZkhlbB-RIQ2G_0y-K9SMg.gif" data-width="1366" data-height="774" src="https://cdn-images-1.medium.com/max/800/1*fZkhlbB-RIQ2G_0y-K9SMg.gif"></div><figcaption class="imageCaption">Easily extract strings to yours .arb files</figcaption></figure><p name="af5c" id="af5c" class="graf graf--p graf-after--figure">Now that you have .arb files you can use tools like <a href="https://translate.google.com/toolkit/docupload" data-href="https://translate.google.com/toolkit/docupload" class="markup--anchor markup--p-anchor" rel="noopener" target="_blank">Google Translator Toolkit</a> to translate your files automatically. Don’t waste your time by making i18n manually. 😎</p><figure name="49ab" id="49ab" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 462px; max-height: 260px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 56.3%;"></div><img class="graf-image" data-image-id="1*QTySKHL2ydHF5XGNcAus8A.gif" data-width="462" data-height="260" src="https://cdn-images-1.medium.com/max/800/1*QTySKHL2ydHF5XGNcAus8A.gif"></div></figure><p name="53a3" id="53a3" class="graf graf--p graf-after--figure">Read more about the plugin in the <a href="https://plugins.jetbrains.com/plugin/10128-flutter-i18n" data-href="https://plugins.jetbrains.com/plugin/10128-flutter-i18n" class="markup--anchor markup--p-anchor" rel="noopener" target="_blank">official page</a>.</p><p name="1f84" id="1f84" class="graf graf--p graf-after--p">That is it for now. Hope you had a nice read. Share and leave your thoughts below in comments. And don’t forget to leave your votes. See you next time.</p>