{"id":133367,"date":"2021-04-06T09:38:00","date_gmt":"2021-04-06T07:38:00","guid":{"rendered":"https:\/\/phrase.com\/blog\/posts\/le-guide-ultime-de-la-localisation-flutter\/"},"modified":"2026-02-26T16:50:33","modified_gmt":"2026-02-26T15:50:33","slug":"flutter-localization","status":"publish","type":"post","link":"https:\/\/phrase.com\/fr\/blog\/posts\/flutter-localization\/","title":{"rendered":"Guide ultime de la localisation Flutter"},"content":{"rendered":"\n\n<p><a href=\"https:\/\/flutter.dev\/\">Flutter<\/a>, le framework d&rsquo;application multiplateforme de Google, a non seulement gagn\u00e9 en popularit\u00e9 dans le domaine du d\u00e9veloppement d&rsquo;applications mobile, mais s&rsquo;est \u00e9galement \u00e9tendu sans effort au web, \u00e0 Linux, \u00e0 macOS et \u00e0 Windows. Pour ne rien g\u00e2cher, Flutter est ultra-rapide et c&rsquo;est un r\u00e9el plaisir d&rsquo;y travailler.<\/p>\n\n\n\n<p>En ce qui concerne l&rsquo;internationalisation (i18n) des applications Flutter, l&rsquo;\u00e9quipe a con\u00e7u une solution int\u00e9gr\u00e9e robuste. Dans ce tutoriel, nous allons voir comment configurer et param\u00e9trer les biblioth\u00e8ques d&rsquo;internationalisation Flutter, les utiliser pour charger et afficher des traductions et travailler sur le format des dates\/heures, parmi d&rsquo;autres fonctionnalit\u00e9s de localisation.<\/p>\n\n\n\n<p>\ud83e\udd3f <em>Pour approfondir\u00a0\u00bb<\/em> Le package de localisation natif de Flutter est bas\u00e9 sur le premier package <a href=\"https:\/\/pub.dev\/packages\/intl\">Dart intl<\/a> :<\/p>\n\n\n\n\n\n<div class=\"wp-block-group acf-blog-cta has-phrase-green-background-color has-background has-global-padding is-layout-constrained wp-block-group-is-layout-constrained\">\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7fc3d43a wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-vertically-aligned-top is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-large is-style-not-rounded\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"806\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2022\/08\/String_Hero-1024x806.png\" alt=\"String Management UI visual | Phrase\" class=\"wp-image-854\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2022\/08\/String_Hero-1024x806.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2022\/08\/String_Hero-300x236.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2022\/08\/String_Hero-768x605.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2022\/08\/String_Hero.png 1260w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow\">\n\n\n<p class=\"subhead has-blue-color has-text-color has-link-color wp-elements-52a8393fcfb59d29e0f5944c62dedea2\" style=\"text-transform:uppercase\">Phrase Strings<\/p>\n\n\n\n<p class=\"has-larger-font-size\"><strong>Take your web or mobile app global without any hassle<\/strong><\/p>\n\n\n\n<p>Adapt your software, <a href=\"https:\/\/phrase.com\/blog\/posts\/website-translation\/\">website<\/a>, or video game for global audiences with the leanest and most realiable software localization platform.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button is-style-grey-filled\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/phrase.com\/platform\/strings\/\">Explore Phrase Strings<\/a>\n<\/div><\/div>\n\n<\/div>\n<\/div>\n<\/div>\n\n\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_81 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\/fr\/blog\/posts\/flutter-localization\/#lapplication-de-demonstration\" >L&rsquo;application de d\u00e9monstration<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/phrase.com\/fr\/blog\/posts\/flutter-localization\/#versions-utilisees\" >Versions utilis\u00e9es<\/a><\/li><\/ul><\/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\/fr\/blog\/posts\/flutter-localization\/#installation-et-configuration\" >Installation et configuration<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/phrase.com\/fr\/blog\/posts\/flutter-localization\/#configuration-de-la-localisation\" >Configuration de la localisation<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/phrase.com\/fr\/blog\/posts\/flutter-localization\/#ajout-des-fichiers-de-traduction\" >Ajout des fichiers de traduction<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/phrase.com\/fr\/blog\/posts\/flutter-localization\/#configuration-de-notre-application\" >Configuration de notre application<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/phrase.com\/fr\/blog\/posts\/flutter-localization\/#generation-de-code-automatique\" >G\u00e9n\u00e9ration de code automatique<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/phrase.com\/fr\/blog\/posts\/flutter-localization\/#utiliser-notre-applocalizations\" >Utiliser notre AppLocalizations<\/a><\/li><\/ul><\/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\/fr\/blog\/posts\/flutter-localization\/#resolution-des-parametres-regionaux\" >R\u00e9solution des param\u00e8tres r\u00e9gionaux<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/phrase.com\/fr\/blog\/posts\/flutter-localization\/#mise-a-jour-du-projet-ios\" >Mise \u00e0 jour du projet iOS<\/a><\/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\/fr\/blog\/posts\/flutter-localization\/#obtenir-le-parametre-regional-actif\" >Obtenir le param\u00e8tre r\u00e9gional actif<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/phrase.com\/fr\/blog\/posts\/flutter-localization\/#messages-de-base-de-traduction\" >Messages de base de traduction<\/a><\/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\/fr\/blog\/posts\/flutter-localization\/#interpolation-dans-les-messages\" >Interpolation dans les messages<\/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\/fr\/blog\/posts\/flutter-localization\/#pluriels\" >Pluriels<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/phrase.com\/fr\/blog\/posts\/flutter-localization\/#format-des-nombres\" >Format des nombres<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/phrase.com\/fr\/blog\/posts\/flutter-localization\/#format-de-date\" >Format de date<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/phrase.com\/fr\/blog\/posts\/flutter-localization\/#sens-de-lecture-de-gauche-a-droite-et-de-droite-a-gauche\" >Sens de lecture\u00a0: de gauche \u00e0 droite et de droite \u00e0 gauche<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/phrase.com\/fr\/blog\/posts\/flutter-localization\/#ajouter-des-ressources-localisees\" >Ajouter des ressources localis\u00e9es<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/phrase.com\/fr\/blog\/posts\/flutter-localization\/#changer-la-langue-dans-lapplication\" >Changer la langue dans l\u2019application<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-20\" href=\"https:\/\/phrase.com\/fr\/blog\/posts\/flutter-localization\/#simplifier-la-localisation-du-contenu-flutter\" >Simplifier la localisation du contenu Flutter<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"lapplication-de-demonstration\"><\/span>L&rsquo;application de d\u00e9monstration<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Pour que ce soit plus concret et plus amusant, nous allons concevoir une petite application de d\u00e9monstration et la localiser :\u00a0<em>H\u00e9ros de l&rsquo;informatique<\/em> pr\u00e9sente une s\u00e9lection de figures notables dans l&rsquo;histoire relativement courte de l&rsquo;informatique.<\/p>\n\n\n\n<figure class=\"wp-block-image wp-image-13861\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-13861\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-app-en-544x1024.png\" alt=\"\u00c9cran d&apos;accueil de l&apos;application Heroes of Computer Science | Phrase\" width=\"350\" height=\"658\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-app-en-544x1024.png 544w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-app-en-159x300.png 159w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-app-en-768x1445.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-app-en-816x1536.png 816w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-app-en.png 1044w\" sizes=\"auto, (max-width: 350px) 100vw, 350px\" \/><figcaption class=\"wp-element-caption\">Notre application en anglais (et bient\u00f4t dans d&rsquo;autres langues)<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"versions-utilisees\"><\/span>Versions utilis\u00e9es<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Dans cet article, nous utilisons les versions suivantes (langues, framework et packages)\u00a0:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Dart 3.1.1<\/li>\n\n\n\n<li>Flutter 3.13.3<\/li>\n\n\n\n<li>DevTools 2.25.0<\/li>\n\n\n\n<li>flutter_localizations (la version semble li\u00e9e \u00e0 Flutter) \u2014 fournit des localisations pour des widgets courants, comme Material ou Cupertino.<\/li>\n\n\n\n<li>intl 0.18.0 \u2014 la colonne vert\u00e9brale du syst\u00e8me de localisation ; nous permet de cr\u00e9er et d&rsquo;utiliser nos propres localisations ; utilis\u00e9 pour le format des dates et des nombres.<\/li>\n\n<\/ul>\n\n\n\n<p>Maintenant, regardons le code de notre application de d\u00e9marrage, qui est assez simple.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\">\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter\/material.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'screens\/hero_list.dart'<\/span>;\n\n<span class=\"hljs-keyword\">void<\/span> main() =&gt; runApp(MyApp());\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">MyApp<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  <span class=\"hljs-meta\">@override<\/span>\n  Widget build(BuildContext context) {\n    <span class=\"hljs-keyword\">return<\/span> MaterialApp(\n      title: <span class=\"hljs-string\">'Heroes of Computer Science'<\/span>,\n      theme: ThemeData(\n        primarySwatch: Colors.blue,\n      ),\n      home: HeroList(title: <span class=\"hljs-string\">'Heroes of Computer Science'<\/span>),\n    );\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Notre widget racine est un <code>MaterialApp<\/code>, avec un <code>HeroList<\/code> \u00e0 sa route <code>home<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter\/material.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter_i18n_2021\/screens\/settings.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter_i18n_2021\/widgets\/hero_card.dart'<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HeroList<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-built_in\">String<\/span> title;\n\n  HeroList({<span class=\"hljs-keyword\">this<\/span>.title = <span class=\"hljs-string\">''<\/span>});\n\n  <span class=\"hljs-meta\">@override<\/span>\n  Widget build(BuildContext context) {\n    <span class=\"hljs-keyword\">return<\/span> Scaffold(\n      appBar: AppBar(\n        title: Text(title),\n        actions: &lt;Widget&gt;&#91;\n          IconButton(\n            icon: Icon(Icons.settings),\n            tooltip: <span class=\"hljs-string\">'Open settings'<\/span>,\n            onPressed: () {\n              Navigator.push(\n                context,\n                MaterialPageRoute(builder: (context) =&gt; Settings()),\n              );\n            },\n          )\n        ],\n      ),\n      body: Padding(\n        padding: <span class=\"hljs-keyword\">const<\/span> EdgeInsets.all(<span class=\"hljs-number\">16<\/span>),\n        child: Column(\n          children: &#91;\n            Padding(\n              padding: <span class=\"hljs-keyword\">const<\/span> EdgeInsets.only(bottom: <span class=\"hljs-number\">8.0<\/span>),\n              child: Text(<span class=\"hljs-string\">'6 Heroes'<\/span>),\n            ),\n            Expanded(\n              child: ListView(\n                children: &lt;Widget&gt;&#91;\n                  HeroCard(\n                    name: <span class=\"hljs-string\">'Grace Hopper'<\/span>,\n                    born: <span class=\"hljs-string\">'9 December 1906'<\/span>,\n                    bio: <span class=\"hljs-string\">'Devised theory of machine...'<\/span>,\n                  ),\n                  HeroCard(\n                    name: <span class=\"hljs-string\">'Alan Turing'<\/span>,\n                    born: <span class=\"hljs-string\">'23 June 1912'<\/span>,\n                    bio: <span class=\"hljs-string\">'Father of theoretical computer...'<\/span>,\n                  ),\n                  <span class=\"hljs-comment\">\/\/ ...<\/span>\n                ],\n              ),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p><code>HeroList<\/code> contient principalement une <code>ListView<\/code> des <code>HeroCard<\/code> param\u00e9tr\u00e9s.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter\/material.dart'<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HeroCard<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  final <span class=\"hljs-built_in\">String<\/span> name;\n  final <span class=\"hljs-built_in\">String<\/span> born;\n  final <span class=\"hljs-built_in\">String<\/span> bio;\n  final <span class=\"hljs-built_in\">String<\/span> imagePath;\n  final <span class=\"hljs-built_in\">String<\/span> placeholderImagePath = <span class=\"hljs-string\">'assets\/images\/placeholder.jpg'<\/span>;\n\n  <span class=\"hljs-keyword\">const<\/span> HeroCard({\n    Key key,\n    <span class=\"hljs-keyword\">this<\/span>.name = <span class=\"hljs-string\">''<\/span>,\n    <span class=\"hljs-keyword\">this<\/span>.born = <span class=\"hljs-string\">''<\/span>,\n    <span class=\"hljs-keyword\">this<\/span>.bio = <span class=\"hljs-string\">''<\/span>,\n    <span class=\"hljs-keyword\">this<\/span>.imagePath,\n  }) : <span class=\"hljs-keyword\">super<\/span>(key: key);\n\n  @override\n  Widget build(BuildContext context) {\n    <span class=\"hljs-keyword\">var<\/span> theme = Theme.of(context);\n\n    <span class=\"hljs-keyword\">return<\/span> Card(\n      child: Padding(\n        padding: <span class=\"hljs-keyword\">const<\/span> EdgeInsets.all(<span class=\"hljs-number\">4.0<\/span>),\n        <span class=\"hljs-attr\">child<\/span>: Row(\n          crossAxisAlignment: CrossAxisAlignment.start,\n          <span class=\"hljs-attr\">children<\/span>: &lt;Widget&gt;&#91;\n            Padding(\n              padding: const EdgeInsets.only(right: 8.0),\n              child: ClipRRect(\n                borderRadius: BorderRadius.circular(2),\n                child: Image.asset(\n                  imagePath ?? placeholderImagePath,\n                  width: 100,\n                  height: 100,\n                ),\n              ),\n            ),\n            Expanded(\n              child: Column(\n                crossAxisAlignment: CrossAxisAlignment.start,\n                children: &lt;Widget&gt;&#91;\n                  Padding(\n                    padding: const EdgeInsets.only(top: 4),\n                    child: Text(\n                      name,\n                      style: theme.textTheme.headline6,\n                    ),\n                  ),\n                  Padding(\n                    padding: const EdgeInsets.only(top: 2, bottom: 4),\n                    child: Text(\n                      born.isEmpty ? '' : 'Born $born',\n                      style: TextStyle(\n                        fontSize: 12,\n                        fontWeight: FontWeight.w300,\n                      ),\n                    ),\n                  ),\n                  Text(\n                    bio,\n                    style: TextStyle(fontSize: 14),\n                  ),\n                ],\n              ),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/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\n<p><code>HeroCard<\/code> affiche l&rsquo;image correspondante et les param\u00e8tres de cha\u00eene dans un widget Material <code>Card<\/code> et pr\u00e9sente l&rsquo;ensemble de mani\u00e8re esth\u00e9tique. Nous pouvons maintenant passer \u00e0 la localisation.<\/p>\n\n\n\n<p>\ud83d\udd17 <em>Ressources \u00bb<\/em> Vous pouvez obtenir le code de l&rsquo;application jusqu&rsquo;\u00e0 ce point \u00e0 partir de la <a href=\"https:\/\/github.com\/PhraseApp-Blog\/flutter-2-i18n-2021\/tree\/start\">branche &lsquo;start&rsquo; de notre d\u00e9p\u00f4t GitHub<\/a>. La <a href=\"https:\/\/github.com\/PhraseApp-Blog\/flutter-2-i18n-2021\/tree\/main\">branche principale<\/a> contient \u00e9galement l&rsquo;application enti\u00e8rement localis\u00e9e.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"installation-et-configuration\"><\/span>Installation et configuration<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Nous pouvons installer nos packages en ajoutant quelques lignes \u00e0 <code>pubspec.yaml<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"YAML\" data-shcb-language-slug=\"yaml\"><span><code class=\"hljs language-yaml\"><span class=\"hljs-attr\">version:<\/span> <span class=\"hljs-number\">1.0<\/span><span class=\"hljs-number\">.0<\/span><span class=\"hljs-string\">+1<\/span>\n\n<span class=\"hljs-attr\">environment:<\/span>\n\u00a0\u00a0<span class=\"hljs-string\">sdk:<\/span>\u00a0<span class=\"hljs-string\">'&gt;=3.1.1\u00a0&lt;4.0.0'<\/span>\n\n<span class=\"hljs-attr\">dependencies:<\/span>\n\u00a0\u00a0<span class=\"hljs-attr\">flutter:<\/span>\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">sdk:<\/span>\u00a0<span class=\"hljs-string\">flutter<\/span>\n\u00a0\u00a0\u00a0\u00a0\n\u00a0\u00a0<span class=\"hljs-string\">cupertino_icons:<\/span>\u00a0<span class=\"hljs-string\">^1.0.2<\/span>\n\n  <span class=\"hljs-comment\"># Add the flutter_localizations package<\/span>\n\u00a0\u00a0<span class=\"hljs-attr\">flutter_localizations:<\/span>\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">sdk:<\/span>\u00a0<span class=\"hljs-string\">flutter<\/span>\n  <span class=\"hljs-comment\"># Add the intl package<\/span>\n\u00a0\u00a0<span class=\"hljs-string\">intl:<\/span>\u00a0<span class=\"hljs-string\">^0.18.0<\/span>\n\n<span class=\"hljs-attr\">dev_dependencies:<\/span>\n\u00a0\u00a0<span class=\"hljs-attr\">flutter_test:<\/span>\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">sdk:<\/span>\u00a0<span class=\"hljs-string\">flutter<\/span>\n\n<span class=\"hljs-attr\">flutter:<\/span>\n\u00a0\u00a0<span class=\"hljs-string\">generate:<\/span>\u00a0<span class=\"hljs-literal\">true<\/span> <span class=\"hljs-comment\"># Add this line<\/span>\n \u00a0<span class=\"hljs-string\">uses-material-design:<\/span>\u00a0<span class=\"hljs-literal\">true<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">YAML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">yaml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Apr\u00e8s avoir ajout\u00e9 les lignes surlign\u00e9es ci-dessus, nous pouvons ex\u00e9cuter\u00a0<code>flutter pub get<\/code>\u00a0\u00e0 partir de la ligne de commande pour r\u00e9cup\u00e9rer nos packages. La ligne <code>generate: true<\/code> est n\u00e9cessaire pour la g\u00e9n\u00e9ration automatique de code que les packages de localisation nous fournissent. Nous approfondirons par la suite l&rsquo;activit\u00e9 de g\u00e9n\u00e9ration de code. Pour l&rsquo;instant, incluez la ligne. Cela peut vous faire gagner beaucoup de temps.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"configuration-de-la-localisation\"><\/span>Configuration de la localisation<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Avec nos packages install\u00e9s, ajoutons un fichier <code>l10n.yaml<\/code> \u00e0 la racine de notre projet. Ce fichier configure l&rsquo;endroit o\u00f9 se trouveront nos fichiers de traduction et les noms des fichiers dart g\u00e9n\u00e9r\u00e9s automatiquement.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"YAML\" data-shcb-language-slug=\"yaml\"><span><code class=\"hljs language-yaml\"><span class=\"hljs-attr\">arb-dir:<\/span> <span class=\"hljs-string\">lib\/l10n<\/span>\n<span class=\"hljs-attr\">template-arb-file:<\/span> <span class=\"hljs-string\">app_en.arb<\/span>\n<span class=\"hljs-attr\">output-localization-file:<\/span> <span class=\"hljs-string\">app_localizations.dart<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">YAML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">yaml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>\ud83d\udd17 <em>Ressources \u00bb<\/em> Le <a href=\"https:\/\/docs.google.com\/document\/d\/10e0saTfAv32OZLRmONy866vnaw0I2jwL8zukykpgWBc\/edit#heading=h.upij01jgi58m\">Guide utilisateur officiel de l&rsquo;internationalisation<\/a> couvre de nombreuses autres options qui peuvent \u00eatre ajout\u00e9es dans <code>l10n.yaml<\/code> pour contr\u00f4ler le g\u00e9n\u00e9rateur de code d&rsquo;internationalisation de Flutter.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"ajout-des-fichiers-de-traduction\"><\/span>Ajout des fichiers de traduction<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>La localisation du contenu Flutter utilise par d\u00e9faut des fichiers ARB (Application Resource Bundle) pour stocker les traductions. Ce sont des fichiers simples \u00e9crits en syntaxe JSON. Au minimum, nous avons besoin d&rsquo;un fichier mod\u00e8le qui correspond \u00e0 nos param\u00e8tres r\u00e9gionaux par d\u00e9faut (l&rsquo;anglais dans notre cas). Nous avons sp\u00e9cifi\u00e9 que notre fichier mod\u00e8le sera <code>lib\/l10n\/app_en.arb<\/code> dans notre configuration ci-dessus. Nous allons maintenant cr\u00e9er ce r\u00e9pertoire de stockage et y ajouter notre fichier de traductions mod\u00e8le.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JSON \/ JSON avec commentaires\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json\">{\n  <span class=\"hljs-attr\">\"appTitle\"<\/span>: <span class=\"hljs-string\">\"Heroes of Computer Science\"<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON avec commentaires<\/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\n<p>Bien s\u00fbr, toutes ces op\u00e9rations n&rsquo;auraient pas beaucoup de sens si nous ne pouvions pas fournir des traductions pour d&rsquo;autres param\u00e8tres r\u00e9gionaux. Dans notre exemple, nous ajouterons un fichier de traductions en arabe. N&rsquo;h\u00e9sitez pas \u00e0 ajouter la langue de votre choix. Nous aborderons les mises en page de droite \u00e0 gauche (RTL) un peu plus tard, donc si cela vous int\u00e9resse, optez pour l&rsquo;arabe ou une autre langue se lisant de droite \u00e0 gauche.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JSON \/ JSON avec commentaires\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json\">{\n  <span class=\"hljs-attr\">\"appTitle\"<\/span>: <span class=\"hljs-string\">\"\u0623\u0628\u0637\u0627\u0644 \u0639\u0644\u0648\u0645 \u0627\u0644\u0643\u0645\u0628\u064a\u0648\u062a\u0631\"<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON avec commentaires<\/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\n<p>Nous pouvons ajouter autant de traductions de param\u00e8tres r\u00e9gionaux que nous le souhaitons. Nous devons simplement nous assurer que nos fichiers respectent la convention de nommage configur\u00e9e : <code>lib\/l10n\/app_&lt;param\u00e8tres r\u00e9gionaux&gt;.arb<\/code><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"configuration-de-notre-application\"><\/span>Configuration de notre application<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Commen\u00e7ons \u00e0 informer notre application de notre vif int\u00e9r\u00eat pour l&rsquo;internationalisation. Nous devons configurer notre fichier <code>main.dart<\/code> pour utiliser les packages de localisation Flutter.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter\/material.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter_localizations\/flutter_localizations.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'screens\/hero_list.dart'<\/span>;\n\n<span class=\"hljs-keyword\">void<\/span> main() =&gt; runApp(MyApp());\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">MyApp<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  @override\n  Widget build(BuildContext context) {\n    <span class=\"hljs-keyword\">return<\/span> MaterialApp(\n      title: <span class=\"hljs-string\">'Heroes of Computer Science'<\/span>,\n      <span class=\"hljs-attr\">localizationsDelegates<\/span>: &#91;\n        GlobalMaterialLocalizations.delegate,\n        GlobalWidgetsLocalizations.delegate,\n        GlobalCupertinoLocalizations.delegate,\n      ],\n      <span class=\"hljs-attr\">supportedLocales<\/span>: &#91;\n        <span class=\"hljs-comment\">\/\/ 'en' is the language code. We could optionally provide a<\/span>\n        <span class=\"hljs-comment\">\/\/ country code as the second param, e.g.<\/span>\n        <span class=\"hljs-comment\">\/\/ Locale('en', 'US'). If we do that, we may want to<\/span>\n        <span class=\"hljs-comment\">\/\/ provide an additional app_en_US.arb file for<\/span>\n        <span class=\"hljs-comment\">\/\/ region-specific translations.<\/span>\n        <span class=\"hljs-keyword\">const<\/span> Locale(<span class=\"hljs-string\">'en'<\/span>, <span class=\"hljs-string\">''<\/span>),\n        <span class=\"hljs-keyword\">const<\/span> Locale(<span class=\"hljs-string\">'ar'<\/span>, <span class=\"hljs-string\">''<\/span>),\n      ],\n      <span class=\"hljs-attr\">theme<\/span>: ThemeData(\n        primarySwatch: Colors.blue,\n      ),\n      <span class=\"hljs-attr\">home<\/span>: HeroList(title: <span class=\"hljs-string\">'Heroes of Computer Science'<\/span>),\n    );\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/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\n<p>Apr\u00e8s avoir import\u00e9 <code>flutter_localizations.dart<\/code>, nous ajoutons les propri\u00e9t\u00e9s <code>localizationsDelegates<\/code> et <code>supportedLocales<\/code> au constructeur <code>MaterialApp<\/code>. Les <code>localizationsDelegates<\/code> fournissent des localisations \u00e0 notre application. Celles incluses ci-dessus fournissent des localisations pour les widgets Flutter, Material et Cupertino, qui ont d\u00e9j\u00e0 \u00e9t\u00e9 localis\u00e9s par l&rsquo;\u00e9quipe Flutter.<\/p>\n\n\n\n<p>Par exemple, supposons que nous avions un <code>MaterialApp<\/code> et que nous appelions <a href=\"https:\/\/api.flutter.dev\/flutter\/material\/showDatePicker.html\">la fonction showDatePicker()<\/a> quelque part dans ce dernier. Supposons \u00e9galement que la langue de notre syst\u00e8me d&rsquo;exploitation soit l&rsquo;arabe ; nous verrions alors quelque chose comme ce qui suit.<\/p>\n\n\n\n<figure class=\"wp-block-image wp-image-13862\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-13862\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-date-picker-ar.png\" alt=\"Calendrier Flutter showDatePicker()\u00a0| Phrase\" width=\"350\" height=\"549\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-date-picker-ar.png 598w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-date-picker-ar-191x300.png 191w\" sizes=\"auto, (max-width: 350px) 100vw, 350px\" \/><\/figure>\n\n\n\n<p>Notez que nous n&rsquo;avons pas eu \u00e0 traduire quoi que ce soit nous-m\u00eames. Le widget de s\u00e9lection de date a d\u00e9j\u00e0 \u00e9t\u00e9 localis\u00e9 par l&rsquo;\u00e9quipe Flutter. Il nous faut juste connecter les bons d\u00e9l\u00e9gu\u00e9s dans le constructeur de l&rsquo;application, comme nous l&rsquo;avons fait ci-dessus. Un grand merci \u00e0 l&rsquo;\u00e9quipe Flutter\u00a0: quel gain de temps\u00a0!<\/p>\n\n\n\n<p>\ud83d\uddd2\ufe0f <em>Remarque\u00a0\u00bb<\/em> Au moment de la r\u00e9daction, <code>flutter_localizations<\/code> <a href=\"https:\/\/flutter.dev\/docs\/development\/accessibility-and-localization\/internationalization#setting-up\">prend en charge 78\u00a0langues<\/a>.<\/p>\n\n\n\n<p>\ud83d\udd17 <em>Ressources \u00bb<\/em> La <a href=\"https:\/\/flutter.dev\/docs\/development\/accessibility-and-localization\/internationalization#how-internationalization-in-flutter-works\">documentation Flutter officielle<\/a> d\u00e9taille comment les diff\u00e9rentes parties, comme les d\u00e9l\u00e9gu\u00e9s et la classe <code>Localizations<\/code>, fonctionnent ensemble pour l\u2019internationalisation\/la localisation.<\/p>\n\n\n\n<p>La propri\u00e9t\u00e9 <code>supportedLocales<\/code> que nous avons fournie au constructeur <code>MaterialApp<\/code> contient la liste des langues que notre application prend en charge. Flutter ne reconstruira <em>que<\/em> les widgets en r\u00e9ponse \u00e0 un changement de param\u00e8tres r\u00e9gionaux si le param\u00e8tre r\u00e9gional est dans la liste <code>supportedLocales<\/code>. Nous reviendrons \u00e0 <code>supportedLocales<\/code> dans un instant lorsque nous discuterons de la r\u00e9solution des param\u00e8tres r\u00e9gionaux. Pour l&rsquo;instant, occupons-nous de la g\u00e9n\u00e9ration du code.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"generation-de-code-automatique\"><\/span>G\u00e9n\u00e9ration de code automatique<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Pour utiliser les traductions dans les fichiers ARB dans notre application Flutter, nous devons g\u00e9n\u00e9rer des fichiers dart que nous importons chaque fois que nous avons besoin des traductions. Pour g\u00e9n\u00e9rer ces fichiers, assurez-vous simplement d&rsquo;avoir suivi les \u00e9tapes d&rsquo;installation et de configuration jusqu&rsquo;\u00e0 ce point et d&rsquo;ex\u00e9cuter l&rsquo;application. Il suffit d&rsquo;ex\u00e9cuter l&rsquo;application. Le code sera g\u00e9n\u00e9r\u00e9 automatiquement et, si tout s&rsquo;est bien pass\u00e9, vous devriez voir les fichiers suivants dans votre r\u00e9pertoire de projet\u00a0:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><code>.dart_tool\/flutter_gen\/gen_l10n\/app_localizations.dart<\/code><\/li>\n\n\n\n<li><code>.dart_tool\/flutter_gen\/gen_l10n\/app_localizations_en.dart<\/code><\/li>\n\n\n\n<li><code>.dart_tool\/flutter_gen\/gen_l10n\/app_localizations_ar.dart<\/code><\/li>\n\n<\/ul>\n\n\n\n<p>\ud83d\uddd2\ufe0f<em> Remarque \u00bb<\/em> Si ces fichiers n&rsquo;ont pas \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9s, assurez-vous que votre application Flutter ne comporte aucune erreur de compilation et v\u00e9rifiez votre console de d\u00e9bogage lorsque vous ex\u00e9cutez l&rsquo;application.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"utiliser-notre-applocalizations\"><\/span>Utiliser notre AppLocalizations<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Utilisons les fichiers de code nouvellement g\u00e9n\u00e9r\u00e9s pour localiser le titre de notre application.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter\/material.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter_i18n_2021\/screens\/settings.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter_localizations\/flutter_localizations.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter_gen\/gen_l10n\/app_localizations.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'screens\/hero_list.dart'<\/span>;\n\n<span class=\"hljs-keyword\">void<\/span> main() =&gt; runApp(MyApp());\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">MyApp<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  <span class=\"hljs-meta\">@override<\/span>\n  Widget build(BuildContext context) {\n    <span class=\"hljs-keyword\">return<\/span> MaterialApp(\n      onGenerateTitle: (context) {\n        <span class=\"hljs-keyword\">return<\/span> AppLocalizations.of(context).appTitle;\n      },\n      localizationsDelegates: &#91;\n        AppLocalizations.delegate,\n        GlobalMaterialLocalizations.delegate,\n        GlobalWidgetsLocalizations.delegate,\n        GlobalCupertinoLocalizations.delegate,\n      ],\n      supportedLocales: &#91;\n        <span class=\"hljs-keyword\">const<\/span> Locale(<span class=\"hljs-string\">'en'<\/span>, <span class=\"hljs-string\">''<\/span>),\n        <span class=\"hljs-keyword\">const<\/span> Locale(<span class=\"hljs-string\">'ar'<\/span>, <span class=\"hljs-string\">''<\/span>),\n      ],\n      theme: ThemeData(\n        primarySwatch: Colors.blue,\n      ),\n      <span class=\"hljs-comment\">\/\/ remove home: HeroList(...)<\/span>\n      initialRoute: <span class=\"hljs-string\">'\/'<\/span>,\n      routes: {\n        <span class=\"hljs-string\">'\/'<\/span>: (context) =&gt; HeroList(title: AppLocalizations.of(context).appTitle),\n        <span class=\"hljs-string\">'\/settings'<\/span>: (context) =&gt; Settings(),\n      },\n    );\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Nous importons <code>app_localizations.dart<\/code> et ajoutons le <code>AppLocalizations.delegate<\/code> g\u00e9n\u00e9r\u00e9 automatiquement \u00e0 notre liste de d\u00e9l\u00e9gu\u00e9s. Cela nous fournit le widget <code>AppLocalizations<\/code>, que nous utilisons pour traduire le titre de l&rsquo;application et le titre de <code>HeroList<\/code>. La propri\u00e9t\u00e9 <code>appTitle<\/code> g\u00e9n\u00e9r\u00e9e automatiquement contiendra la traduction correspondant au param\u00e8tre r\u00e9gional actif, extrait de notre fichier <code>app_&lt;locale&gt;.arb<\/code>.<\/p>\n\n\n\n<p>\u270b <em>Avertissement \u00bb<\/em> En raison de l&rsquo;ordre de chargement, nos traductions ne seront pas pr\u00eates lorsque nous construisons notre <code>MaterialApp<\/code>. Nous utilisons donc les propri\u00e9t\u00e9s <code>onGenerateTitle<\/code> et <code>routes<\/code>, et leurs fonctions de constructeur <code>(context) {}<\/code> pour nous assurer que nos traductions sont pr\u00eates lorsque nous d\u00e9finissons nos cha\u00eenes de titre.<\/p>\n\n\n\n<p>Maintenant, si nous d\u00e9finissons la langue de notre syst\u00e8me d&rsquo;exploitation sur l&rsquo;arabe et que nous ex\u00e9cutons notre application, voil\u00e0 ce qu&rsquo;on obtient.<\/p>\n\n\n\n<figure class=\"wp-block-image wp-image-13863\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-13863\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-ar-title-544x1024.png\" alt=\"Appli Heroes of Computer Science avec titre arabe | Phrase\" width=\"350\" height=\"658\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-ar-title-544x1024.png 544w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-ar-title-159x300.png 159w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-ar-title-768x1445.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-ar-title-816x1536.png 816w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-ar-title.png 1044w\" sizes=\"auto, (max-width: 350px) 100vw, 350px\" \/><\/figure>\n\n\n\n<p>Le titre est maintenant en arabe. De plus, remarquez comment Flutter a automatiquement organis\u00e9 de nombreux widgets dans une direction de droite \u00e0 gauche pour nous. L&rsquo;arabe \u00e9tant une langue qui se lit de droite \u00e0 gauche, cela nous fait gagner beaucoup de temps\u00a0! Il va falloir corriger l&rsquo;espacement \u00e0 gauche de l&rsquo;image dans les <code>HeroCard<\/code>, nous le ferons un peu plus tard lorsque nous aborderons la question du sens de lecture.<\/p>\n\n\n\n<p>\ud83e\udd3f <em>Pour approfondir\u00a0\u00bb<\/em> Le lecteur avis\u00e9 a peut-\u00eatre remarqu\u00e9 que <code>AppLocalizations.of(context)<\/code> ressemble beaucoup \u00e0 l&rsquo;appel d&rsquo;un <a href=\"https:\/\/api.flutter.dev\/flutter\/widgets\/InheritedWidget-class.html\">InheritedWidget<\/a>. C&rsquo;est parce que le fonctionnement des objets de localisation est similaire aux <code>InheritedWidget<\/code>.<\/p>\n\n\n\n<p>Voil\u00e0, la configuration est termin\u00e9e. Nous disposons d\u00e9sormais des bases n\u00e9cessaires \u00e0 la localisation de notre application. Vous vous demandez peut-\u00eatre \u00e0 ce stade comment Flutter d\u00e9cide du param\u00e8tre r\u00e9gional \u00e0 utiliser. Voyons \u00e7a.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"resolution-des-parametres-regionaux\"><\/span>R\u00e9solution des param\u00e8tres r\u00e9gionaux<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Les param\u00e8tres r\u00e9gionaux que nous avons fournis \u00e0 <code>MaterialApp(supportedLocales: [...])<\/code> sont les seuls que Flutter utilisera pour d\u00e9terminer le param\u00e8tre r\u00e9gional actif lorsque l&rsquo;application s&rsquo;ex\u00e9cute. Pour ce faire, Flutter utilise trois propri\u00e9t\u00e9s d&rsquo;un param\u00e8tre r\u00e9gional\u00a0:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Le code de langue, par exemple <code>'en'<\/code> pour l\u2019anglais<\/li>\n\n\n\n<li>Le code de pays (facultatif) : par exemple, la partie <code>US<\/code> dans <code>en_US<\/code><\/li>\n\n\n\n<li><a href=\"https:\/\/flutter.dev\/docs\/development\/accessibility-and-localization\/internationalization#advanced-locale-definition\">Le code de script<\/a> (facultatif) \u2014 l&rsquo;ensemble de lettres utilis\u00e9, par exemple le chinois traditionnel (<code>Hant<\/code>) ou le chinois simplifi\u00e9 (<code>Hans<\/code>)<\/li>\n\n<\/ul>\n\n\n\n<p>Par d\u00e9faut, Flutter lira les param\u00e8tres r\u00e9gionaux syst\u00e8me pr\u00e9f\u00e9r\u00e9s de l&rsquo;utilisateur et\u00a0:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n\n<li>Essayez de faire correspondre <code>languageCode<\/code>, <code>scriptCode<\/code> et <code>countryCode<\/code> avec l&rsquo;un de ceux dans <code>supportedLocales<\/code>. Sinon,<\/li>\n\n\n\n<li>Essayez de faire correspondre <code>languageCode<\/code> and <code>scriptCode<\/code> avec l\u2019un de ceux dans <code>supportedLocales<\/code>. Sinon,<\/li>\n\n\n\n<li>Essayez de faire correspondre <code>languageCode<\/code> and <code>countryCode<\/code> avec l&rsquo;un de ceux dans <code>supportedLocales<\/code>. Sinon,<\/li>\n\n\n\n<li>Essayez de faire correspondre <code>languageCode<\/code> avec l&rsquo;un de ceux dans <code>supportedLocales<\/code>. Sinon,<\/li>\n\n\n\n<li>Essayez de faire correspondre <code>countryCode<\/code> avec l&rsquo;un de ceux dans <code>supportedLocales<\/code>, uniquement aucun param\u00e8tre r\u00e9gional pr\u00e9f\u00e9r\u00e9 ne correspond pas. Sinon,<\/li>\n\n\n\n<li>\u00c0 d\u00e9faut, utilisez le premier \u00e9l\u00e9ment de <code>supportedLocales<\/code> en solution de secours.<\/li>\n\n<\/ol>\n\n\n\n<p>Dans le cas de notre application, si la langue iOS de l\u2019utilisateur est d\u00e9finie sur <code>ar_SA<\/code>, il verra nos localisations <code>ar<\/code> (cf. 4. ci-dessus). Si la langue iOS de l&rsquo;utilisateur est d\u00e9finie sur <code>fr<\/code> (fran\u00e7ais), il verra nos localisations <code>en<\/code> (cf. 6 ci-dessus). Sur <a href=\"https:\/\/phrase.com\/blog\/posts\/best-practices-for-android-localization-revisited-and-expanded\/\">Android<\/a>, un utilisateur peut avoir une liste de param\u00e8tres r\u00e9gionaux pr\u00e9f\u00e9r\u00e9s, et pas uniquement un. Cette situation est couverte par Flutter dans l&rsquo;algorithme de r\u00e9solution ci-dessus.<\/p>\n\n\n\n<p>\ud83d\udd17 Ressources \u00bb L&rsquo;algorithme ci-dessus est une reformulation de la <a href=\"https:\/\/api.flutter.dev\/flutter\/widgets\/WidgetsApp\/supportedLocales.html\">documentation officielle de la propri\u00e9t\u00e9 supportedLocales<\/a>.<\/p>\n\n\n\n<p>\u270b <em>Avertissement :<\/em> Si votre application prend en charge un param\u00e8tre linguistique avec un code pays, comme <code>fr_CA<\/code> (fran\u00e7ais canadien), vous devez fournir une solution de secours sans le code pays, comme <code>fr<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"mise-a-jour-du-projet-ios\"><\/span>Mise \u00e0 jour du projet iOS<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>La documentation officielle Flutter mentionne la n\u00e9cessit\u00e9 de mettre \u00e0 jour <code>Info.plist<\/code> directement dans le paquet de l&rsquo;application <a href=\"https:\/\/phrase.com\/blog\/posts\/ios-tutorial-internationalization-localization\/\">iOS<\/a>, en ajoutant nos param\u00e8tres r\u00e9gionaux pris en charge. Si <code>Info.plist<\/code> n&rsquo;est pas mis \u00e0 jour, notre application iOS pourrait ne pas fonctionner comme pr\u00e9vu. Pour effectuer la mise \u00e0 jour, il suffit d&rsquo;ouvrir <code>ios\/Runner\/Info.plist<\/code> dans n&rsquo;importe quel \u00e9diteur de texte et de s&rsquo;assurer que les entr\u00e9es suivantes y figurent.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Texte brut\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">&lt;key&gt;CFBundleLocalizations&lt;\/key&gt;\n&lt;array&gt;\n  &lt;string&gt;en&lt;\/string&gt;\n  &lt;string&gt;ar&lt;\/string&gt;\n&lt;\/array&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Texte brut<\/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\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"obtenir-le-parametre-regional-actif\"><\/span>Obtenir le param\u00e8tre r\u00e9gional actif<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Nous devons parfois conna\u00eetre le param\u00e8tre r\u00e9gional d&rsquo;ex\u00e9cution dans notre code. Nous pouvons le faire avec le morceau de code suivant.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\">Locale activeLocale = Localizations.localeOf(context);\n\n<span class=\"hljs-comment\">\/\/ Assuming our active locale is fr_CA...<\/span>\ndebugPrint(activeLocale.languageCode);\n<span class=\"hljs-comment\">\/\/ =&gt; fr<\/span>\n\ndebugPrint(activeLocale.countryCode);\n<span class=\"hljs-comment\">\/\/ =&gt; CA<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>\u270b <em>Avertissement \u00bb<\/em> Remarquez que nous utilisons <code>Localizations<\/code>, un widget int\u00e9gr\u00e9 \u00e0 Flutter, et non <code>AppLocalizations<\/code> g\u00e9n\u00e9r\u00e9 automatiquement.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"messages-de-base-de-traduction\"><\/span>Messages de base de traduction<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Nous avons d\u00e9j\u00e0 couvert les messages de traduction de base lorsque nous avons ajout\u00e9 notre message <code>appTitle<\/code>. Cependant, passons rapidement en revue le flux de travaux pour ajouter des messages. Nous allons traduire l&rsquo;info-bulle du bouton d&rsquo;ic\u00f4ne de la barre d&rsquo;application de notre <code>HeroList<\/code>. Autant en <em>profiter<\/em> un peu puisque nous ne construisons pas vraiment un \u00e9cran de param\u00e8tres \ud83d\ude05.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\"><span class=\"hljs-comment\">\/\/ ...<\/span>\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HeroList<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-built_in\">String<\/span> title;\n\n  HeroList({<span class=\"hljs-keyword\">this<\/span>.title = <span class=\"hljs-string\">''<\/span>});\n\n  <span class=\"hljs-meta\">@override<\/span>\n  Widget build(BuildContext context) {\n    <span class=\"hljs-keyword\">return<\/span> Scaffold(\n      appBar: AppBar(\n        title: Text(title),\n        actions: &lt;Widget&gt;&#91;\n          IconButton(\n            icon: Icon(Icons.settings),\n            tooltip: <span class=\"hljs-string\">'Open settings'<\/span>,\n            onPressed: () {\n              Navigator.push(\n                context,\n                MaterialPageRoute(builder: (context) =&gt; Settings()),\n              );\n            },\n          )\n        ],\n      ),\n      body: ...\n  );\n}\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Nous allons nous occuper de localiser cette info-bulle. Tout d&rsquo;abord, nous allons ajouter les entr\u00e9es pertinentes \u00e0 nos fichiers ARB.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"JSON \/ JSON avec commentaires\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json\"><span class=\"hljs-comment\">\/\/ English<\/span>\n{\n  <span class=\"hljs-attr\">\"appTitle\"<\/span>: <span class=\"hljs-string\">\"Heroes of Computer Science\"<\/span>,\n  <span class=\"hljs-attr\">\"openSettings\"<\/span>: <span class=\"hljs-string\">\"Open Settings\"<\/span>\n}\n\n<span class=\"hljs-comment\">\/\/ Arabic<\/span>\n{\n  <span class=\"hljs-attr\">\"appTitle\"<\/span>: <span class=\"hljs-string\">\"\u0623\u0628\u0637\u0627\u0644 \u0639\u0644\u0648\u0645 \u0627\u0644\u0643\u0645\u0628\u064a\u0648\u062a\u0631\"<\/span>,\n  <span class=\"hljs-attr\">\"openSettings\"<\/span>: <span class=\"hljs-string\">\"\u0625\u0641\u062a\u062d \u0627\u0644\u0625\u0639\u062f\u0627\u062f\u0627\u062a\"<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON avec commentaires<\/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\n<p>Nous allons <em>recharger notre application pour r\u00e9g\u00e9n\u00e9rer nos fichiers de code<\/em>. Cette \u00e9tape est vraiment importante et l&rsquo;oublier peut entra\u00eener une frustration inutile. Notez qu&rsquo;il s&rsquo;agit d&rsquo;un red\u00e9marrage complet de l&rsquo;application (<\/p>\n\n\n\n<figure class=\"wp-block-image alignnone wp-image-13872\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-13872\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-app-reload-1.png\" alt=\"Bouton de rafra\u00eechissement | Phrase\" width=\"24\" height=\"24\" \/><\/figure>\n\n\n\n<p>), et non d&rsquo;un rechargement \u00e0 chaud.<\/p>\n\n\n\n<p>Maintenant, nous pouvons mettre \u00e0 jour notre code pour utiliser notre nouveau message localis\u00e9.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\"><span class=\"hljs-comment\">\/\/ ... <\/span>\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter_gen\/gen_l10n\/app_localizations.dart'<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HeroList<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-built_in\">String<\/span> title;\n\n  HeroList({<span class=\"hljs-keyword\">this<\/span>.title = <span class=\"hljs-string\">''<\/span>});\n\n  <span class=\"hljs-meta\">@override<\/span>\n  Widget build(BuildContext context) {\n    <span class=\"hljs-keyword\">var<\/span> t = AppLocalizations.of(context);\n\n    <span class=\"hljs-keyword\">return<\/span> Scaffold(\n      appBar: AppBar(\n        title: Text(title),\n        actions: &lt;Widget&gt;&#91;\n          IconButton(\n            icon: Icon(Icons.settings),\n            tooltip: t.openSettings,\n            onPressed: () {\n              Navigator.push(\n                context,\n                MaterialPageRoute(builder: (context) =&gt; Settings()),\n              );\n            },\n          )\n        ],\n      ),\n      body: ... \n    );\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Tout \u00e9tant en ordre pour ce code, lorsque nous rechargerons notre application, nous devrions voir la valeur localis\u00e9e de notre info-bulle dans l&rsquo;<em>inspecteur de widget<\/em>.<\/p>\n\n\n\n<figure class=\"wp-block-image wp-image-13864 size-full\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-13864 size-full\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-ar-tooltip.png\" alt=\"Info-bulle de l&apos;inspecteur de widget | Phrase\" width=\"400\" height=\"152\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-ar-tooltip.png 400w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/04\/flutteri18n2021p1-ar-tooltip-300x114.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/figure>\n\n\n\n<p>\u270b <em>Avertissement \u00bb<\/em> Il est possible que votre IDE vous <a href=\"https:\/\/docs.google.com\/document\/d\/10e0saTfAv32OZLRmONy866vnaw0I2jwL8zukykpgWBc\/edit#heading=h.xru0hle4tb2x\">indique une erreur<\/a> apr\u00e8s l&rsquo;ajout de nouveaux messages de traduction. Si vous avez recharg\u00e9 votre application, l&rsquo;erreur peut \u00eatre incorrecte (il se peut que tout fonctionne correctement). Si vous obtenez un message indiquant qu&rsquo;il y a des erreurs de compilation, vous pouvez essayer de lancer l&rsquo;application quand m\u00eame. Tant que l&rsquo;application se compile et s&rsquo;ex\u00e9cute et que vous voyez vos nouvelles traductions, tout fonctionne probablement correctement. Pour faire dispara\u00eetre l&rsquo;erreur dans l&rsquo;IDE, fermez compl\u00e8tement votre application, puis red\u00e9marrez-la.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"interpolation-dans-les-messages\"><\/span>Interpolation dans les messages<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Nous sommes bien partis pour traduire notre application. Mais qu&rsquo;en est-il de l&rsquo;interpolation des valeurs dynamiques d&rsquo;ex\u00e9cution dans nos messages de traduction\u00a0? Par exemple, la biographie de Steve Wozniak contient les noms de produits <em>Apple\u00a0I<\/em> et <em>Apple\u00a0II<\/em>.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\"><span class=\"hljs-comment\">\/\/ ... <\/span>\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HeroList<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/\/ ... <\/span>\n\n  <span class=\"hljs-meta\">@override<\/span>\n  Widget build(BuildContext context) {\n    <span class=\"hljs-keyword\">return<\/span> Scaffold(\n      <span class=\"hljs-comment\">\/\/ ... <\/span>\n      body: HeroCard(\n        name: <span class=\"hljs-string\">'Steve Wozniak'<\/span>,\n        born: <span class=\"hljs-string\">'11 August 1950'<\/span>,\n        bio: <span class=\"hljs-string\">'Designed &amp; developed the Apple I &amp; '<\/span>\n             <span class=\"hljs-string\">'Apple II microcomputers.'<\/span>,\n        imagePath: <span class=\"hljs-string\">'assets\/images\/steve_wozniak.jpg'<\/span>,\n      ),\n      <span class=\"hljs-comment\">\/\/ ... <\/span>\n    );\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Lorsque nous localisons ce message, nous pourrions vouloir garder <em>Apple I<\/em> et <em>Apple II<\/em> en anglais, peu importe les param\u00e8tres r\u00e9gionaux actifs. Pour ce faire, nous pouvons utiliser un espace r\u00e9serv\u00e9 dans nos fichiers de traduction.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"JSON \/ JSON avec commentaires\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json\"><span class=\"hljs-comment\">\/\/ English<\/span>\n{\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n  <span class=\"hljs-attr\">\"wozniakBio\"<\/span>: <span class=\"hljs-string\">\"Developed the {appleOne} &amp; {appleTwo} microcomputers.\"<\/span>,\n  <span class=\"hljs-attr\">\"@wozniakBio\"<\/span>: {\n    <span class=\"hljs-attr\">\"placeholders\"<\/span>: {\n      <span class=\"hljs-attr\">\"appleOne\"<\/span>: {},\n      <span class=\"hljs-attr\">\"appleTwo\"<\/span>: {}\n    }\n  },\n  \n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n}\n\n<span class=\"hljs-comment\">\/\/ Arabic<\/span>\n{\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n  <span class=\"hljs-attr\">\"wozniakBio\"<\/span>: <span class=\"hljs-string\">\"\u0637\u0648\u0631 \u062c\u0647\u0627\u0632\u064a \u0643\u0645\u0628\u064a\u0648\u062a\u0631 {appleOne} \u0648 {appleTwo}\"<\/span>,\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON avec commentaires<\/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\n<p>Nous utilisons la syntaxe <code>{placeholderName}<\/code> pour d\u00e9finir les espaces r\u00e9serv\u00e9s pour nos valeurs dynamiques et nous pouvons avoir autant d&rsquo;espaces r\u00e9serv\u00e9s que nous le souhaitons dans un message.<\/p>\n\n\n\n<p>Vous avez probablement aussi remarqu\u00e9 la cl\u00e9 <code>@wozniakBio<\/code> dans nos traductions anglaises ci-dessus. Cette entr\u00e9e est un compl\u00e9ment au message <code>wozniakBio<\/code> dans le m\u00eame fichier. Les entr\u00e9es compl\u00e9mentaires sont facultatives pour les messages de base, mais requises pour les messages avec des espaces r\u00e9serv\u00e9s. En fait, nous utilisons des entr\u00e9es compl\u00e9mentaires pour d\u00e9finir les espaces r\u00e9serv\u00e9s des messages (<a href=\"https:\/\/docs.google.com\/document\/d\/10e0saTfAv32OZLRmONy866vnaw0I2jwL8zukykpgWBc\/edit#heading=h.emv7twpb8iyo\">entre autres choses<\/a>).<\/p>\n\n\n\n<p>\ud83d\uddd2\ufe0f <em>Remarque\u00a0\u00bb<\/em> L&rsquo;entr\u00e9e compl\u00e9mentaire pour un message avec la cl\u00e9 <code>foo<\/code> doit avoir une cl\u00e9 de <code>@foo<\/code>. Nous n&rsquo;avons besoin d&rsquo;entr\u00e9es compl\u00e9mentaires que dans notre fichier de traduction par d\u00e9faut\/mod\u00e8le (l&rsquo;anglais dans notre cas).<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-string\">\"@wozniakBio\"<\/span>: { <span class=\"hljs-string\">\"placeholders\"<\/span>: { <span class=\"hljs-string\">\"appleOne\"<\/span>: {}, <span class=\"hljs-string\">\"appleTwo\"<\/span>: {} } }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/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\n<p>\u270b <em>Avertissement \u00bb<\/em> Les noms d&rsquo;espaces r\u00e9serv\u00e9s doivent \u00eatre des noms de param\u00e8tres de m\u00e9thode dart valides.<\/p>\n\n\n\n<p>Nous pourrions utiliser l&rsquo;objet <code>placeholders<\/code> pour sp\u00e9cifier le type de chaque valeur, et m\u00eame fournir des exemples comme documentation si nous le souhaitons. Nous pouvons \u00e9galement laisser la d\u00e9finition comme un vide <code>{}<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-string\">\"@wozniakBio\"<\/span>: {\n    <span class=\"hljs-string\">\"placeholders\"<\/span>: {\n      <span class=\"hljs-string\">\"appleOne\"<\/span>: {\n        <span class=\"hljs-comment\">\/\/ Explicit type<\/span>\n        <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"String\"<\/span>,\n        <span class=\"hljs-comment\">\/\/ A little doc<\/span>\n        <span class=\"hljs-string\">\"example\"<\/span>: <span class=\"hljs-string\">\"Apple I\"<\/span>\n      },\n      <span class=\"hljs-comment\">\/\/ It's perfectly ok to just specifiy the name<\/span>\n      <span class=\"hljs-string\">\"appleTwo\"<\/span>: {}\n    }\n  }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Le <code>type<\/code> est utilis\u00e9 dans la m\u00e9thode que Flutter g\u00e9n\u00e9rera sur <code>AppLocalizations<\/code> pour notre message <code>wozniakBio<\/code>.<\/p>\n\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-comment\">\/\/ ... <\/span>\n\nabstract <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">AppLocalizations<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/\/ ... <\/span>\n\n  <span class=\"hljs-comment\">\/\/ This method is implemented in app_localizations_en.dart<\/span>\n  <span class=\"hljs-comment\">\/\/ and app_localizations_ar.dart.<\/span>\n  <span class=\"hljs-comment\">\/\/ Explicit type for appleOne parameter. Implicit appleTwo<\/span>\n  <span class=\"hljs-comment\">\/\/ parameter.<\/span>\n  <span class=\"hljs-built_in\">String<\/span> wozniakBio(<span class=\"hljs-built_in\">String<\/span> appleOne, <span class=\"hljs-built_in\">Object<\/span> appleTwo);\n\n  <span class=\"hljs-comment\">\/\/ ... <\/span>\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/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\n<p>\ud83d\uddd2\ufe0f <em>Remarque \u00bb<\/em> Il est parfaitement acceptable dans la plupart des cas d&rsquo;utiliser <code>{}<\/code> vide pour les d\u00e9finitions des espaces r\u00e9serv\u00e9s. Une d\u00e9finition vide fera en sorte que le param\u00e8tre soit de type <code>Object<\/code>. Flutter utilisera simplement la valeur <code>theParameter.toString()<\/code> du param\u00e8tre concern\u00e9, donc un param\u00e8tre <code>Object<\/code> fonctionnera parfaitement. Un espace r\u00e9serv\u00e9 <code>Object<\/code> implicite garde \u00e9galement nos messages flexibles pour prendre n&rsquo;importe quel type, puisque tous les types dart d\u00e9rivent de <a href=\"https:\/\/api.dart.dev\/stable\/2.12.4\/dart-core\/Object-class.html\">Object<\/a> et ont un <code>toString()<\/code>.<\/p>\n\n\n\n<p>Apr\u00e8s avoir relanc\u00e9 l&rsquo;application pour mettre \u00e0 jour <code>AppLocalizations<\/code>, nous pouvons localiser le message de la biographie de Woz avec la nouvelle m\u00e9thode.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\"><span class=\"hljs-comment\">\/\/ ... <\/span>\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HeroList<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/\/ ... <\/span>\n\n  <span class=\"hljs-meta\">@override<\/span>\n  Widget build(BuildContext context) {\n    <span class=\"hljs-keyword\">var<\/span> t = AppLocalizations.of(context);\n\n    <span class=\"hljs-keyword\">return<\/span> Scaffold(\n      <span class=\"hljs-comment\">\/\/ ... <\/span>\n      body: HeroCard(\n        name: <span class=\"hljs-string\">'Steve Wozniak'<\/span>,\n        born: <span class=\"hljs-string\">'11 August 1950'<\/span>,\n        bio: t.wozniakBio(<span class=\"hljs-string\">'Apple I'<\/span>, <span class=\"hljs-string\">'Apple II'<\/span>),\n        imagePath: <span class=\"hljs-string\">'assets\/images\/steve_wozniak.jpg'<\/span>,\n      ),\n      <span class=\"hljs-comment\">\/\/ ... <\/span>\n    );\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Maintenant, nous avons l&rsquo;assurance de ne jamais \u00eatre poursuivis par des entreprises pour avoir mal repr\u00e9sent\u00e9 leurs produits dans <em>n&rsquo;importe quelle<\/em> langue.<\/p>\n\n\n\n<figure class=\"wp-block-image wp-image-14105\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-14105\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-woz-bio-ar-en-1024x702.png\" alt=\"Valeurs interpol\u00e9es en arabe et en anglais | Phrase\" width=\"550\" height=\"377\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-woz-bio-ar-en-1024x702.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-woz-bio-ar-en-300x206.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-woz-bio-ar-en-768x527.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-woz-bio-ar-en.png 1070w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><figcaption class=\"wp-element-caption\">Valeurs interpol\u00e9es en arabe et en anglais<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"pluriels\"><\/span>Pluriels<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Nous devons souvent g\u00e9rer des pluriels dynamiques dans nos op\u00e9rations de localisation. \u00ab\u00a0Vous avez re\u00e7u <em>un message<\/em>\u00a0\u00bb ou \u00ab\u00a0Vous avez re\u00e7u <em>3 messages<\/em>\u00ab\u00a0, par exemple.<\/p>\n\n\n\n<p>Il est important de noter que <a href=\"https:\/\/unicode-org.github.io\/cldr-staging\/charts\/latest\/supplemental\/language_plural_rules.html\">les langues g\u00e8rent les pluriels diff\u00e9remment<\/a>. Par exemple, l&rsquo;anglais a deux formes plurielles : one et other (other == z\u00e9ro et &gt;1). L&rsquo;arabe en a six. Cela peut poser quelques difficult\u00e9s lors de la localisation en utilisant des biblioth\u00e8ques qui ne prennent pas en charge les r\u00e8gles de pluriels complexes. Heureusement, la solution d&rsquo;internationalisation officielle de Flutter g\u00e8re les pluriels complexes, ce qui correspond \u00e0 nos besoins. Utilisons-la pour localiser le compteur de h\u00e9ros dans notre application.<\/p>\n\n\n\n<figure class=\"wp-block-image wp-image-14106\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-14106\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-hero-count-before-l10n-1024x616.png\" alt=\"\u00c9cran d&apos;accueil de l&apos;application Heroes of Computer Science, pluralisation en anglais | Phrase\" width=\"550\" height=\"331\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-hero-count-before-l10n-1024x616.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-hero-count-before-l10n-300x180.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-hero-count-before-l10n-768x462.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-hero-count-before-l10n.png 1169w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/figure>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\"><span class=\"hljs-comment\">\/\/ ...<\/span>\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HeroList<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n\n  <span class=\"hljs-meta\">@override<\/span>\n  Widget build(BuildContext context) {\n    <span class=\"hljs-keyword\">return<\/span> Scaffold(\n      <span class=\"hljs-comment\">\/\/ ...<\/span>\n      body: Padding(\n        <span class=\"hljs-comment\">\/\/ ...<\/span>\n        child: Column(\n          children: &#91;\n            Padding(\n              padding: <span class=\"hljs-keyword\">const<\/span> EdgeInsets.only(bottom: <span class=\"hljs-number\">8.0<\/span>),\n              <span class=\"hljs-comment\">\/\/ Localized string should replace '6 Heroes'<\/span>\n              child: Text(<span class=\"hljs-string\">'6 Heroes'<\/span>), \n            ),\n            <span class=\"hljs-comment\">\/\/ ...<\/span>\n          ],\n        ),\n      ),\n    );\n  }\n}\n\n<span class=\"hljs-comment\">\/\/ ...<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Tout d&rsquo;abord, ajoutons le message \u00e0 notre fichier mod\u00e8le ARB en anglais.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"JSON \/ JSON avec commentaires\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json\">{\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n  <span class=\"hljs-attr\">\"heroCount\"<\/span>: <span class=\"hljs-string\">\"{count,plural, =0{No heroes yet} =1{1 hero} other{{count} heroes}}\"<\/span>,\n  <span class=\"hljs-attr\">\"@heroCount\"<\/span>: {\n    <span class=\"hljs-attr\">\"placeholders\"<\/span>: {\n      <span class=\"hljs-attr\">\"count\"<\/span>: {}\n    }\n  },\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON avec commentaires<\/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\n<p>Nous sp\u00e9cifions un espace r\u00e9serv\u00e9 <code>count<\/code> dans notre message et nous l&rsquo;utilisons avec la syntaxe sp\u00e9ciale <code>{count,plural,...}<\/code> pour d\u00e9finir les diff\u00e9rentes formes plurielles.<\/p>\n\n\n\n<p>\u270b <em>Avertissement \u00bb<\/em>\u00a0: Le param\u00e8tre <code>count<\/code> sera toujours de type <code>int<\/code>. Si vous sp\u00e9cifiez un autre type pour <code>count<\/code>, Flutter l&rsquo;ignorera et utilisera <code>int<\/code> de toute fa\u00e7on.<\/p>\n\n\n\n<p>\ud83d\uddd2\ufe0f <em>Remarque \u00bb<\/em> Vous pouvez ajouter d&rsquo;autres espaces r\u00e9serv\u00e9s que <code>count<\/code> pour un message pluriel ; ils sont sp\u00e9cifi\u00e9s comme d&rsquo;habitude (voir la section <em>Interpolation<\/em> ci-dessus).<\/p>\n\n\n\n<p>Flutter prend en charge les formes plurielles suivantes.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>zero \u279e <code>=0{No heroes}<\/code><\/li>\n\n\n\n<li>one \u279e <code>=1{One hero}<\/code><\/li>\n\n\n\n<li>two \u279e <code>=2(Two heroes}<\/code><\/li>\n\n\n\n<li>few \u279e <code>few{The {count} heroes}<\/code><\/li>\n\n\n\n<li>many \u279e <code>many{{count} heroes}<\/code><\/li>\n\n\n\n<li>other \u279e <code>other{{count} heroes}<\/code><\/li>\n\n<\/ul>\n\n\n\n<p><code>few<\/code>, <code>many<\/code> et <code>other<\/code> <a href=\"https:\/\/unicode-org.github.io\/cldr-staging\/charts\/latest\/supplemental\/language_plural_rules.html\">ont des significations diff\u00e9rentes selon la langue active<\/a>. La seule forme requise dans <em>n&rsquo;importe quelle<\/em> langue est la forme <code>other<\/code>.<\/p>\n\n\n\n<p>\ud83d\uddd2\ufe0f <em>Remarque \u00bb<\/em> Nous n&rsquo;avions pas besoin d&rsquo;utiliser la forme zero <code>=0<\/code> dans notre message en anglais ci-dessus. En cas d&rsquo;omission, Flutter aurait utilis\u00e9 notre forme <code>other<\/code> \u00e0 la place.<\/p>\n\n\n\n<p>Ajoutons maintenant notre message en arabe. Comme nous l&rsquo;avons mentionn\u00e9 plus t\u00f4t, l&rsquo;arabe a six formes plurielles.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"JSON \/ JSON avec commentaires\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json\">{\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n  <span class=\"hljs-attr\">\"heroCount\"<\/span>: <span class=\"hljs-string\">\"{count,plural, =0{\u0644\u0627 \u062a\u0648\u062c\u062f \u0623\u0628\u0637\u0627\u0644 \u0628\u0639\u062f} =1{\u0628\u0637\u0644 \u0648\u0627\u062d\u062f} =2{\u0628\u0637\u0644\u0627\u0646} few{{count} \u0623\u0628\u0637\u0627\u0644} many{{count} \u0628\u0637\u0644} other{{count} \u0628\u0637\u0644}}\"<\/span>,\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON avec commentaires<\/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\n<p>Maintenant, connectons le tout et utilisons notre nouveau message dans notre widget <code>HeroList<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\"><span class=\"hljs-comment\">\/\/ ...<\/span>\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HeroList<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n\n  <span class=\"hljs-meta\">@override<\/span>\n  Widget build(BuildContext context) {\n    <span class=\"hljs-keyword\">var<\/span> t = AppLocalizations.of(context);\n    <span class=\"hljs-keyword\">return<\/span> Scaffold(\n      <span class=\"hljs-comment\">\/\/ ...<\/span>\n      body: Padding(\n        <span class=\"hljs-comment\">\/\/ ...<\/span>\n        child: Column(\n          children: &#91;\n            Padding(\n              padding: <span class=\"hljs-keyword\">const<\/span> EdgeInsets.only(bottom: <span class=\"hljs-number\">8.0<\/span>),\n              child: Text(t.heroCount(<span class=\"hljs-number\">6<\/span>)),\n            ),\n            <span class=\"hljs-comment\">\/\/ ...<\/span>\n          ],\n        ),\n      ),\n    );\n  }\n}\n\n<span class=\"hljs-comment\">\/\/ ...<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Bien s\u00fbr, dans une application de production, le param\u00e8tre count pass\u00e9 \u00e0 <code>t.heroCount()<\/code> serait dynamique. Flutter choisit la bonne forme plurielle de notre message en fonction des param\u00e8tres r\u00e9gionaux actifs.<\/p>\n\n\n\n<figure class=\"wp-block-image wp-image-14107\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-14107\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-en-plural-forms-1024x379.png\" alt=\"Formes plurielles anglaises dans notre application | Phrase\" width=\"500\" height=\"185\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-en-plural-forms-1024x379.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-en-plural-forms-300x111.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-en-plural-forms-768x284.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-en-plural-forms.png 1485w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><figcaption class=\"wp-element-caption\">Formes plurielles anglaises dans notre application<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image wp-image-14108\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-14108\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-ar-plural-forms-1024x716.png\" alt=\"Formes plurielles arabes dans notre application\u00a0| Phrase\" width=\"500\" height=\"350\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-ar-plural-forms-1024x716.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-ar-plural-forms-300x210.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-ar-plural-forms-768x537.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-ar-plural-forms.png 1485w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><figcaption class=\"wp-element-caption\">Formes plurielles arabes dans notre application<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"format-des-nombres\"><\/span>Format des nombres<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Nous pouvons formater les nombres dans nos messages localis\u00e9s en utilisant notre ami l&rsquo;objet <code>placeholders<\/code> dans les entr\u00e9es compagnon de notre fichier mod\u00e8le ARB (anglais dans notre cas). Notre application de d\u00e9monstration ne permet pas d&rsquo;aborder la question du formatage des nombres, donc nous allons simplement pr\u00e9tendre pour la d\u00e9monstration que nous avons une application de commerce \u00e9lectronique.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"JSON \/ JSON avec commentaires\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json\"><span class=\"hljs-comment\">\/\/ app_en.arb in example app that has a shopping cart <\/span>\n{\n  <span class=\"hljs-attr\">\"itemTotal\"<\/span>: <span class=\"hljs-string\">\"Your total is: {value}\"<\/span>,\n  <span class=\"hljs-attr\">\"@itemTotal\"<\/span>: {\n    <span class=\"hljs-attr\">\"placeholders\"<\/span>: {\n      <span class=\"hljs-attr\">\"value\"<\/span>: {\n        <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"double\"<\/span>,\n        <span class=\"hljs-attr\">\"format\"<\/span>: <span class=\"hljs-string\">\"currency\"<\/span>\n      }\n    }\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON avec commentaires<\/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\n<p>Nous avons sp\u00e9cifi\u00e9 un <code>type<\/code> explicite et un <code>format<\/code> pour contr\u00f4ler la fa\u00e7on dont le nombre sera affich\u00e9. Comme d&rsquo;habitude, nous pouvons traduire notre message dans nos autres fichiers de param\u00e8tres r\u00e9gionaux.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"JSON \/ JSON avec commentaires\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json\"><span class=\"hljs-comment\">\/\/ app_ar.arb in example app that has a shopping cart<\/span>\n{ <span class=\"hljs-attr\">\"itemTotal\"<\/span>: <span class=\"hljs-string\">\"\u0625\u062c\u0645\u0627\u0644\u064a: {value}\"<\/span> }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON avec commentaires<\/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\n<p>Apr\u00e8s avoir recharg\u00e9 notre application, nous pouvons utiliser notre message comme d&rsquo;habitude.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-27\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\"><span class=\"hljs-comment\">\/\/ In a Widget<\/span>\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter_gen\/gen_l10n\/app_localizations.dart'<\/span>;\n\n<span class=\"hljs-comment\">\/\/ In some widget builder with a context<\/span>\n<span class=\"hljs-keyword\">var<\/span> t = AppLocalizations.of(context);\n<span class=\"hljs-keyword\">var<\/span> message = t.itemTotal(<span class=\"hljs-number\">56.12<\/span>);\n<span class=\"hljs-comment\">\/\/ =&gt; \"Your total is USD56.12\" when current locale is English<\/span>\n<span class=\"hljs-comment\">\/\/ =&gt; \"\u0625\u062c\u0645\u0627\u0644\u064a: EGP56.12\" when current locale is Arabic<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>\u270b <em>Avertissement \u00bb<\/em> Vous ne pouvez pas remplacer les <code>format<\/code>s de nombres selon les param\u00e8tres linguistiques. Le format que vous sp\u00e9cifiez dans vos param\u00e8tres linguistiques mod\u00e8les (l&rsquo;anglais dans notre cas) sera utilis\u00e9 pour les autres param\u00e8tres linguistiques, ind\u00e9pendamment de tout changement du <code>format<\/code> que vous sp\u00e9cifiez dans vos autres fichiers de param\u00e8tres linguistiques.<\/p>\n\n\n\n<p>N&rsquo;oubliez pas qu&rsquo;en coulisses, Flutter utilise la biblioth\u00e8que <a href=\"https:\/\/pub.dev\/packages\/intl\">Dart intl<\/a> pour la plupart de son travail d&rsquo;internationalisation. Le format de devise que nous avons utilis\u00e9 ci-dessus est l&rsquo;un des formats int\u00e9gr\u00e9s au formateur de nombres intl. Les autres formats incluent notamment des d\u00e9cimales et des pourcentages.<\/p>\n\n\n\n<p>\ud83d\udd17 <em>Ressources\u00a0\u00bb<\/em> Consultez le <a href=\"https:\/\/docs.google.com\/document\/d\/10e0saTfAv32OZLRmONy866vnaw0I2jwL8zukykpgWBc\/edit#heading=h.4jrxhcva98zs\">guide utilisateur officiel<\/a> pour conna\u00eetre tous les formats disponibles.<\/p>\n\n\n\n<p>Cependant, nous n&rsquo;avons pas besoin que Flutter internationalise les nombres. Nous pouvons utiliser intl directement pour avoir plus de contr\u00f4le sur notre format de nombre.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-28\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter_gen\/gen_l10n\/app_localizations.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:intl\/intl.dart'<\/span>;\n\n<span class=\"hljs-comment\">\/\/ In some Widget builder with a context<\/span>\n<span class=\"hljs-keyword\">var<\/span> currentLocale = AppLocalizations.of(context).localeName;\n<span class=\"hljs-keyword\">var<\/span> compact = NumberFormat.compact(locale: currentLocale).format(<span class=\"hljs-number\">6000000<\/span>);\n<span class=\"hljs-comment\">\/\/ =&gt; \"6M\" when current locale is US English<\/span>\n<span class=\"hljs-comment\">\/\/ =&gt; \"\u0666 \u0645\u0644\u064a\u0648\u0646\" when current locale is Egyptian Arabic<\/span>\n\n<span class=\"hljs-keyword\">var<\/span> simpleCurrency = NumberFormat.simpleCurrency(locale: currentLocale).format(<span class=\"hljs-number\">14.24<\/span>);\n<span class=\"hljs-comment\">\/\/ =&gt; \"$14.24\" when current locale is US English<\/span>\n<span class=\"hljs-comment\">\/\/ =&gt; \"\u062c.\u0645.\u200f \u0661\u0664\u066b\u0662\u0664\" when current locale is Egyptian Arabic<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-28\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>\ud83d\udd17 <em>Ressources \u00bb<\/em> Vous n&rsquo;avez pas besoin d&rsquo;utiliser les formats pr\u00e9d\u00e9finis comme <code>compact<\/code> et <code>simpleCurrency<\/code>. Le constructeur d&rsquo;internationalisation <code>NumberFormat<\/code> vous donne un contr\u00f4le pr\u00e9cis sur vos formats de nombre. Pour en savoir plus, reportez-vous \u00e0 la <a href=\"https:\/\/pub.dev\/documentation\/intl\/latest\/intl\/NumberFormat-class.html\">documentation officielle<\/a>.<\/p>\n\n\n\n<p>\u270b <em>Avertissement \u00bb<\/em> La seule fa\u00e7on d&rsquo;obtenir des chiffres arabes orientaux (\u0661\u060c\u0662\u060c\u0663\u2026) pour l&rsquo;arabe est de d\u00e9finir le param\u00e8tre <code>locale<\/code> sur <code>\"ar_EG\"<\/code> (arabe \u00e9gyptien). Ni <code>\"ar\"<\/code> ni aucune variante <code>\"ar_XX\"<\/code> autre que l&rsquo;\u00e9gyptien n&rsquo;ont fonctionn\u00e9 pour moi.<\/p>\n\n\n\n<p>\u270b <em>Avertissement \u00bb<\/em> Les formats n&rsquo;ont pas fonctionn\u00e9 avec la variable plurielle <code>count<\/code> pour moi. Il semble que Flutter remplace le format lorsqu&rsquo;il traite les pluriels. Si vous parvenez \u00e0 obtenir des formats dans vos pluriels, veuillez nous faire savoir comment vous avez fait dans les commentaires ci-dessous.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"format-de-date\"><\/span>Format de date<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Nos h\u00e9ros ont actuellement des dates de naissance cod\u00e9es en dur qui ne sont pas localis\u00e9es, ce qui n&rsquo;est pas id\u00e9al.<\/p>\n\n\n\n<figure class=\"wp-block-image wp-image-14109\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-14109\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-unlocalized-date-1024x332.png\" alt=\"Format de date anglais dans la localisation arabe | Phrase\" width=\"550\" height=\"178\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-unlocalized-date-1024x332.png 1024w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-unlocalized-date-300x97.png 300w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-unlocalized-date-768x249.png 768w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-unlocalized-date.png 1115w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><figcaption class=\"wp-element-caption\">Nous voulons que cette date soit localis\u00e9e en arabe<\/figcaption><\/figure>\n\n\n\n<p>Rappelez-vous que nos h\u00e9ros sont trait\u00e9s via un widget <code>HeroCard<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-29\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter\/material.dart'<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HeroCard<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-built_in\">String<\/span> name;\n  <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-built_in\">String<\/span> born;\n  <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-built_in\">String<\/span> bio;\n  <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-built_in\">String<\/span> imagePath;\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n\n  <span class=\"hljs-keyword\">const<\/span> HeroCard({\n    Key key,\n    <span class=\"hljs-keyword\">this<\/span>.name = <span class=\"hljs-string\">''<\/span>,\n    <span class=\"hljs-keyword\">this<\/span>.born = <span class=\"hljs-string\">''<\/span>,\n    <span class=\"hljs-keyword\">this<\/span>.bio = <span class=\"hljs-string\">''<\/span>,\n    <span class=\"hljs-keyword\">this<\/span>.imagePath,\n  }) : <span class=\"hljs-keyword\">super<\/span>(key: key);\n\n  <span class=\"hljs-meta\">@override<\/span>\n  Widget build(BuildContext context) {\n    <span class=\"hljs-comment\">\/\/ ...<\/span>\n    <span class=\"hljs-keyword\">return<\/span> Card(\n      child: Padding(\n        <span class=\"hljs-comment\">\/\/ ...<\/span>\n        Padding(\n          padding: <span class=\"hljs-keyword\">const<\/span> EdgeInsets.only(top: <span class=\"hljs-number\">2<\/span>, bottom: <span class=\"hljs-number\">4<\/span>),\n          child: Text(\n            born.isEmpty ? <span class=\"hljs-string\">''<\/span> : <span class=\"hljs-string\">'Born <span class=\"hljs-subst\">$born<\/span>'<\/span>,\n            <span class=\"hljs-comment\">\/\/ ...<\/span>\n          ),\n        ),\n        <span class=\"hljs-comment\">\/\/ ...<\/span>\n      ),\n    );\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-29\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Pour formater la <code>date de naissance<\/code> pour les diff\u00e9rents param\u00e8tres r\u00e9gionaux pris en charge par notre application, nous ajoutons d&rsquo;abord quelques nouveaux messages localis\u00e9s avec des valeurs de date interpol\u00e9es.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-30\" data-shcb-language-name=\"JSON \/ JSON avec commentaires\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json\"><span class=\"hljs-comment\">\/\/ English<\/span>\n{\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n  <span class=\"hljs-attr\">\"heroBorn\"<\/span>: <span class=\"hljs-string\">\"Born {date}\"<\/span>,\n  <span class=\"hljs-attr\">\"@heroBorn\"<\/span>: {\n    <span class=\"hljs-attr\">\"placeholders\"<\/span>: {\n      <span class=\"hljs-attr\">\"date\"<\/span>: {\n        <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"DateTime\"<\/span>,\n        <span class=\"hljs-attr\">\"format\"<\/span>: <span class=\"hljs-string\">\"yMMMd\"<\/span>\n      }\n    }\n  },\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n}\n\n<span class=\"hljs-comment\">\/\/ Arabic<\/span>\n{\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n  <span class=\"hljs-attr\">\"heroBorn\"<\/span>: <span class=\"hljs-string\">\"\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u0645\u064a\u0644\u0627\u062f {date}\"<\/span>,\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-30\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON avec commentaires<\/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\n<p>Lorsque nous d\u00e9finissons notre espace r\u00e9serv\u00e9 <code>date<\/code> dans notre fichier de localisation mod\u00e8le, nous devons lui attribuer le type <code>DateTime<\/code>. Nous pouvons ensuite utiliser <code>format<\/code> pour sp\u00e9cifier la mani\u00e8re dont nous voulons afficher la date. Le format <code>yMMMd<\/code> que nous avons d\u00e9fini ci-dessus correspond \u00e0 \u00ab\u00a0ann\u00e9e, mois abr\u00e9g\u00e9, jour\u00a0\u00bb, ce qui en anglais am\u00e9ricain donnerait quelque chose comme \u00ab\u00a0Dec 9, 1906\u00a0\u00bb.<\/p>\n\n\n\n<p>\ud83d\udd17 <em>Resources \u00bb<\/em> En coulisses, Flutter utilise simplement la classe d&rsquo;internationalisation <code>DateFormat<\/code>, g\u00e9n\u00e9rant du code comme <code>DateFormat.yMMMd(localeName).format(date)<\/code>. Le constructeur nomm\u00e9 <code>yMMMd<\/code> est un raccourci pratique appel\u00e9 \u00ab\u00a0squelette\u00a0\u00bb et il en existe plusieurs que vous pouvez utiliser. Pour en savoir plus, consultez la <a href=\"https:\/\/pub.dev\/documentation\/intl\/latest\/intl\/DateFormat-class.html\">documentation officielle DateFormat<\/a>.<\/p>\n\n\n\n<p>\ud83d\uddd2\ufe0f\u00a0<em>Remarque \u00bb<\/em> Nous n&rsquo;avons pas eu \u00e0 appeler notre variable d&rsquo;espace r\u00e9serv\u00e9 <code>date<\/code>. Nous aurions pu lui donner n&rsquo;importe quel nom, tant que c&rsquo;\u00e9tait un nom de param\u00e8tre de fonction Dart valide.<\/p>\n\n\n\n<p>Connectons cela dans notre widget pour afficher nos nouveaux messages.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-31\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter\/material.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:intl\/intl.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter_gen\/gen_l10n\/app_localizations.dart'<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HeroCard<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-built_in\">String<\/span> name;\n  <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-built_in\">String<\/span> born;\n  <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-built_in\">String<\/span> bio;\n  <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-built_in\">String<\/span> imagePath;\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n  <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-built_in\">DateTime<\/span> bornDateTime;\n\n  HeroCard({\n    Key key,\n    <span class=\"hljs-keyword\">this<\/span>.name = <span class=\"hljs-string\">''<\/span>,\n    <span class=\"hljs-keyword\">this<\/span>.born = <span class=\"hljs-string\">''<\/span>,\n    <span class=\"hljs-keyword\">this<\/span>.bio = <span class=\"hljs-string\">''<\/span>,\n    <span class=\"hljs-keyword\">this<\/span>.imagePath,\n  }) : bornDateTime = DateFormat(<span class=\"hljs-string\">'d MMMM yyyy'<\/span>).parse(born),\n       <span class=\"hljs-keyword\">super<\/span>(key: key);\n\n  <span class=\"hljs-meta\">@override<\/span>\n  Widget build(BuildContext context) {\n    <span class=\"hljs-comment\">\/\/ ...<\/span>\n    <span class=\"hljs-keyword\">var<\/span> t = AppLocalizations.of(context);\n    <span class=\"hljs-keyword\">return<\/span> Card(\n      child: Padding(\n        <span class=\"hljs-comment\">\/\/ ...<\/span>\n        Padding(\n          padding: <span class=\"hljs-keyword\">const<\/span> EdgeInsets.only(top: <span class=\"hljs-number\">2<\/span>, bottom: <span class=\"hljs-number\">4<\/span>),\n          child: Text(\n            born.isEmpty ? <span class=\"hljs-string\">''<\/span> : t.heroBorn(bornDateTime),\n            <span class=\"hljs-comment\">\/\/ ...<\/span>\n          ),\n        ),\n        <span class=\"hljs-comment\">\/\/ ...<\/span>\n      ),\n    );\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-31\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>La date de naissance des h\u00e9ros se pr\u00e9sentant sous la forme <code>String<\/code>, nous devons d&rsquo;abord la parser en <code>DateTime<\/code>. Pour ce faire, nous utilisons la classe d&rsquo;internationalisation <code>DateFormat<\/code> dans notre constructeur de widget.<\/p>\n\n\n\n<p>Dans la m\u00e9thode <code>build<\/code>, nous passons simplement le <code>DateTime<\/code> pars\u00e9 \u00e0 notre message localis\u00e9 <code>t.heroBorn()<\/code>. Cela nous donne des dates correctement localis\u00e9es.<\/p>\n\n\n\n<figure class=\"wp-block-image wp-image-14121\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-14121\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-en-date-1.png\" alt=\"Version anglaise de la carte d&apos;Alan Turing | Phrase\" width=\"550\" height=\"178\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-en-date-1.png 583w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-en-date-1-300x97.png 300w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image wp-image-14111\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-14111\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-ar-date.png\" alt=\"Version arabe de la carte d&apos;Alan Turing | Phrase\" width=\"550\" height=\"201\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-ar-date.png 583w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-ar-date-300x110.png 300w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/figure>\n\n\n\n<p>Si nous ne voulons pas utiliser l&rsquo;un des squelettes pr\u00e9d\u00e9finis, comment personnaliser compl\u00e8tement nos formats de date\u00a0? Comme pour le formatage des nombres (voir ci-dessus), nous utiliserions directement la classe <code>intl.DateFormat<\/code>. Supposons que nous voulions afficher les dates de naissance des h\u00e9ros au format 1912-06-23. Nous proc\u00e9derions comme suit.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-32\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:intl\/intl.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter_gen\/gen_l10n\/app_localizations.dart'<\/span>;\n\n<span class=\"hljs-comment\">\/\/ In widget builder with context<\/span>\n<span class=\"hljs-keyword\">var<\/span> t = AppLocalizations.of(context);\n<span class=\"hljs-keyword\">var<\/span> bornDateTime = DateTime(<span class=\"hljs-number\">1912<\/span>, <span class=\"hljs-number\">6<\/span>, <span class=\"hljs-number\">23<\/span>);\n<span class=\"hljs-keyword\">var<\/span> formattedBorn = DateFormat(<span class=\"hljs-string\">'yyyy-MM-dd'<\/span>, t.localeName).format(bornDateTime);\n<span class=\"hljs-keyword\">var<\/span> message = t.heroBorn(formattedBorn);\n<span class=\"hljs-comment\">\/\/ =&gt; \"1912-06-23\" in US English<\/span>\n<span class=\"hljs-comment\">\/\/ =&gt; \"\u0661\u0669\u0661\u0662-\u0660\u0666-\u0662\u0663\" in Egyptian Arabic<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-32\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/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\n<p>Nos messages localis\u00e9s <code>heroBorn<\/code> dans nos fichiers ARB prendraient alors simplement des param\u00e8tres r\u00e9guliers <code>Object<\/code> ou <code>String<\/code>, puisque nous avons d\u00e9j\u00e0 fait le formatage pour ces derniers.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"sens-de-lecture-de-gauche-a-droite-et-de-droite-a-gauche\"><\/span>Sens de lecture\u00a0: de gauche \u00e0 droite et de droite \u00e0 gauche<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Alors que l&rsquo;anglais est une langue qui se lit de gauche \u00e0 droite (LTR), l&rsquo;arabe se lit dans l&rsquo;autre sens, de droite \u00e0 gauche (RTL). Cela pose un probl\u00e8me lorsque notre application est utilis\u00e9e sur un appareil avec l\u2019arabe comme langue syst\u00e8me.<\/p>\n\n\n\n<figure class=\"wp-block-image wp-image-14114\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-14114\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-broken-ar.png\" alt=\"Version arabe de l&apos;application Heroes of Computer Science avec un espacement insuffisant | Phrase\" width=\"550\" height=\"520\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-broken-ar.png 662w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-broken-ar-300x284.png 300w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><figcaption class=\"wp-element-caption\">Notez le manque d&rsquo;espacement entre les images et le texte<\/figcaption><\/figure>\n\n\n\n<p>L&rsquo;image et le texte dans chaque carte sont align\u00e9s car nous utilisons <code>EdgeInsets.only(right)<\/code> pour d\u00e9finir l&rsquo;espacement autour de notre image.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-33\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:intl\/intl.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter_gen\/gen_l10n\/app_localizations.dart'<\/span>;\n\n<span class=\"hljs-comment\">\/\/ In widget builder with context<\/span>\n<span class=\"hljs-keyword\">var<\/span> t = AppLocalizations.of(context);\n<span class=\"hljs-keyword\">var<\/span> bornDateTime = <span class=\"hljs-built_in\">DateTime<\/span>(<span class=\"hljs-number\">1912<\/span>, <span class=\"hljs-number\">6<\/span>, <span class=\"hljs-number\">23<\/span>);\n<span class=\"hljs-keyword\">var<\/span> formattedBorn = DateFormat(<span class=\"hljs-string\">'yyyy-MM-dd'<\/span>, t.localeName).format(bornDateTime);\n<span class=\"hljs-keyword\">var<\/span> message = t.heroBorn(formattedBorn);\n<span class=\"hljs-comment\">\/\/ =&gt; \"1912-06-23\" in US English<\/span>\n<span class=\"hljs-comment\">\/\/ =&gt; \"\u0661\u0669\u0661\u0662-\u0660\u0666-\u0662\u0663\" in Egyptian Arabic<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-33\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Cela fonctionne dans les langues s&rsquo;\u00e9crivant de gauche \u00e0 droite (LTR), o\u00f9 nous voulons un espace \u00e0 droite entre l&rsquo;image et le texte. En revanche, dans les langues s&rsquo;\u00e9crivant de droite \u00e0 gauche (RTL), nous voulons un espace \u00e0 <em>gauche<\/em>.<\/p>\n\n\n\n<p>Il suffit d&rsquo;utiliser <code>EdgeInsetsDirectional<\/code> au lieu de <code>EdgeInsets<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-34\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/...<\/span>\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HeroCard<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n\n  @override\n  Widget build(BuildContext context) {\n    <span class=\"hljs-comment\">\/\/ ...<\/span>\n    <span class=\"hljs-keyword\">return<\/span> Card(\n      child: Padding(\n        padding: <span class=\"hljs-keyword\">const<\/span> EdgeInsets.all(<span class=\"hljs-number\">4.0<\/span>),\n        child: Row(\n          crossAxisAlignment: CrossAxisAlignment.start,\n          children: &lt;Widget&gt;&#91;\n            Padding(\n              padding: <span class=\"hljs-keyword\">const<\/span> EdgeInsetsDirectional.only(end: <span class=\"hljs-number\">8.0<\/span>),\n              child: ClipRRect(\n                <span class=\"hljs-comment\">\/\/ Portrait image...<\/span>\n              ),\n            ),\n            Expanded(\n              <span class=\"hljs-comment\">\/\/ Text widgets...<\/span>\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-34\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Remarquez que nous utilisons <code>end<\/code> au lieu de <code>right<\/code> pour d\u00e9finir l&rsquo;espacement entre l&rsquo;image et le texte. <code>EdgeInsetsDirectional<\/code> est l&rsquo;un des quelques widgets de mise en page Flutter qui g\u00e8rent le sens de lecture des param\u00e8tres r\u00e9gionaux. Ces widgets utilisent les param\u00e8tres <code>start<\/code> et <code>end<\/code>, au lieu de <code>left<\/code> et <code>right<\/code>. Ces widgets directionnels font automatiquement ce qui convient pour les param\u00e8tres r\u00e9gionaux actifs\u00a0:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><code>start<\/code> == <code>left<\/code> pour les langues se lisant de gauche \u00e0 droite (LTR)<\/li>\n\n\n\n<li><code>start<\/code> == <code>right<\/code> pour les langues se lisant de droite \u00e0 gauche (RTL)<\/li>\n\n\n\n<li><code>end<\/code> == <code>right<\/code> pour les langues se lisant de gauche \u00e0 droite (LTR)<\/li>\n\n\n\n<li><code>end<\/code> == <code>left <\/code> pour les langues se lisant de droite \u00e0 gauche (RTL)<\/li>\n\n<\/ul>\n\n\n\n<p>Gr\u00e2ce \u00e0 ce petit ajustement du code, notre probl\u00e8me de mise en page est r\u00e9solu.<\/p>\n\n\n\n<figure class=\"wp-block-image wp-image-14115\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-14115\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-fixed-ar.png\" alt=\"Version arabe de l&apos;application Heroes of Computer Science avec espacement | Phrase\" width=\"550\" height=\"517\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-fixed-ar.png 664w, https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-fixed-ar-300x282.png 300w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><figcaption class=\"wp-element-caption\">La mise en page s&rsquo;adapte maintenant au sens de lecture des param\u00e8tres r\u00e9gionaux actifs.<\/figcaption><\/figure>\n\n\n\n<p>\ud83d\udd17 <em>Ressources \u00bb<\/em> Au moment de la r\u00e9daction, la documentation officielle de Flutter inclut les widgets directionnels suivants\u00a0:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><a href=\"https:\/\/api.flutter.dev\/flutter\/painting\/EdgeInsetsDirectional-class.html\">EdgeInsetsDirectional<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/api.flutter.dev\/flutter\/painting\/AlignmentDirectional-class.html\">AlignmentDirectional<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/api.flutter.dev\/flutter\/painting\/BorderDirectional-class.html\">BorderDirectional<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/api.flutter.dev\/flutter\/painting\/BorderRadiusDirectional-class.html\">BorderRadiusDirectional<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/api.flutter.dev\/flutter\/widgets\/PositionedDirectional-class.html\">PositionedDirectional<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/api.flutter.dev\/flutter\/widgets\/AnimatedPositionedDirectional-class.html\">AnimatedPositionedDirectional<\/a><\/li>\n\n<\/ul>\n\n\n\n<p>Voil\u00e0, notre application finale est globalis\u00e9e.<\/p>\n\n\n\n<figure class=\"wp-block-image wp-image-14142\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-14142\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2021\/05\/flutteri18n2021p2-final-en-ar-1-e1699439769197.png\" alt=\"Versions arabe et anglaise de l&apos;application Heroes of Computer Science c\u00f4te \u00e0 c\u00f4te | Phrase\" width=\"800\" height=\"693\" \/><\/figure>\n\n\n\n<p>\ud83d\udd17 Ressources\u00a0\u00bb Obtenez le code complet de notre application de d\u00e9monstration depuis <a href=\"https:\/\/github.com\/PhraseApp-Blog\/flutter-2-i18n-2021\">notre d\u00e9p\u00f4t GitHub<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"ajouter-des-ressources-localisees\"><\/span>Ajouter des ressources localis\u00e9es<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>La localisation des images dans Flutter implique d&rsquo;utiliser diff\u00e9rents ensembles d&rsquo;images pour les diff\u00e9rents param\u00e8tres r\u00e9gionaux ou les diff\u00e9rentes langues dans votre application. Cela se fait g\u00e9n\u00e9ralement pour afficher des images avec du texte ou un contenu correspondant \u00e0 la langue pr\u00e9f\u00e9r\u00e9e de l&rsquo;utilisateur.<\/p>\n\n\n\n<p>Ajoutons un drapeau, qui s&rsquo;affiche diff\u00e9remment selon la r\u00e9gion de l&rsquo;utilisateur.<\/p>\n\n\n\n<figure class=\"wp-block-image wp-image-68808\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-68808\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/10\/flutter-l10n-flag-language.png\" alt=\"Drapeau du pays ajout\u00e9 \u00e0 une application Flutter localis\u00e9e | Phrase\" width=\"550\" height=\"764\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/10\/flutter-l10n-flag-language.png 618w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/10\/flutter-l10n-flag-language-216x300.png 216w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/figure>\n\n\n\n<p>Nous commencerons par ajouter les images, une pour chaque param\u00e8tre r\u00e9gional que nous pr\u00e9voyons de prendre en charge. Nous allons organiser ces images dans une structure de dossiers bas\u00e9e sur les param\u00e8tres r\u00e9gionaux, par exemple\u00a0:<!-- notionvc: fc5508b4-43d5-43ba-a914-18ef9baa152d --><\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-35\" data-shcb-language-name=\"Texte brut\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">\u2514\u2500\u2500 assets\/\n    \u2514\u2500\u2500 images\/\n        \u251c\u2500\u2500 eg\/\n        \u2502   \u2514\u2500\u2500 flag.jpg\n        \u251c\u2500\u2500 us\/\n        \u2502   \u2514\u2500\u2500 flag.jpg\n        \u2514\u2500\u2500 flag.jpg<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-35\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Texte brut<\/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\n<p>Pour ce tutoriel, nous allons ajouter les images des drapeaux de l\u2019\u00c9gypte et des \u00c9tats-Unis. Le fichier directement dans le dossier images (sans param\u00e8tres r\u00e9gionaux) est une image de secours pour les autres r\u00e9gions.<\/p>\n\n\n\n<p>Ensuite, enregistrez les fichiers dans le fichier <code>pubspec.yml<\/code>.<\/p>\n\n\n\n<p><!-- notionvc: 8d2588ec-6a65-4ecd-a48b-892e51f0c4be --><\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-36\" data-shcb-language-name=\"YAML\" data-shcb-language-slug=\"yaml\"><span><code class=\"hljs language-yaml\"><span class=\"hljs-comment\"># pubspec.yml<\/span>\n\n<span class=\"hljs-comment\"># ...<\/span>\n\n<span class=\"hljs-attr\">flutter:<\/span>\n  <span class=\"hljs-comment\"># ...<\/span>\n  <span class=\"hljs-attr\">assets:<\/span>\n  <span class=\"hljs-comment\"># ...<\/span>\n    <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">assets\/images\/in\/flag.jpg<\/span>\n    <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">assets\/images\/us\/flag.jpg<\/span>\n    <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">assets\/images\/flag.jpg<\/span>\n\n<span class=\"hljs-comment\"># ...<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-36\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">YAML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">yaml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Maintenant, nous pouvons charger les images dans notre fichier <code>hero_list.dart<\/code> :<!-- notionvc: 8a12d860-6906-4664-bced-66bf768073ee --><\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-37\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\">\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter\/material.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter_gen\/gen_l10n\/app_localizations.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'..\/widgets\/hero_card.dart'<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HeroList<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n\n  <span class=\"hljs-meta\">@override<\/span>\n  Widget build(BuildContext context) {\n    <span class=\"hljs-comment\">\/\/ ...<\/span>\n    <span class=\"hljs-built_in\">String<\/span> getImagePath(<span class=\"hljs-built_in\">String<\/span> imageName) {\n      <span class=\"hljs-built_in\">String<\/span> basePath = <span class=\"hljs-string\">'assets\/images\/'<\/span>;\n\n      <span class=\"hljs-comment\">\/\/ When country code isn't supported, we<\/span>\n      <span class=\"hljs-comment\">\/\/ display fallback image.<\/span>\n      <span class=\"hljs-keyword\">if<\/span> (locale.countryCode?.isEmpty == <span class=\"hljs-keyword\">true<\/span>) {\n        <span class=\"hljs-keyword\">return<\/span>  basePath + <span class=\"hljs-string\">'flag.jpg'<\/span>;\n      }\n\n      <span class=\"hljs-built_in\">String<\/span> localePath = <span class=\"hljs-string\">'<span class=\"hljs-subst\">${locale.countryCode!.toLowerCase()}<\/span>\/'<\/span>;\n      <span class=\"hljs-keyword\">return<\/span> basePath + localePath + imageName;\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> Scaffold(\n      <span class=\"hljs-comment\">\/\/ ...<\/span>\n      body: Padding(\n        padding: <span class=\"hljs-keyword\">const<\/span> EdgeInsets.all(<span class=\"hljs-number\">16<\/span>),\n        child: Column(\n          children: &#91;\n\t    <span class=\"hljs-comment\">\/\/ ...<\/span>\n            Padding(\n              padding: <span class=\"hljs-keyword\">const<\/span> EdgeInsets.only(bottom: <span class=\"hljs-number\">2.0<\/span>),\n              child: Image.asset(\n                getImagePath(<span class=\"hljs-string\">'flag.jpg'<\/span>),\n                width: <span class=\"hljs-number\">40<\/span>,\n                height: <span class=\"hljs-number\">40<\/span>,\n              ),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-37\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Maintenant, dans le fichier <code>main.dart<\/code>, apportez les modifications suivantes<!-- notionvc: bb9617c5-f2af-4173-becf-6ef08ae5d950 --><\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-38\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\">...\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">MyApp<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> MyApp({<span class=\"hljs-keyword\">super<\/span>.key});\n\n  <span class=\"hljs-comment\">\/\/ This widget is the root of your application.<\/span>\n  <span class=\"hljs-meta\">@override<\/span>\n  Widget build(BuildContext context) {\n    <span class=\"hljs-keyword\">return<\/span> MaterialApp(\n    ...    \n    supportedLocales: &#91;\n        <span class=\"hljs-keyword\">const<\/span> Locale(<span class=\"hljs-string\">'ar'<\/span>, <span class=\"hljs-string\">''<\/span>),\n        <span class=\"hljs-keyword\">const<\/span> Locale(<span class=\"hljs-string\">'en'<\/span>, <span class=\"hljs-string\">''<\/span>),\n\t\t\t\t<span class=\"hljs-comment\">\/\/ Add the supported region codes <\/span>\n        <span class=\"hljs-keyword\">const<\/span> Locale(<span class=\"hljs-string\">'ar'<\/span>, <span class=\"hljs-string\">'EG'<\/span>),\n        <span class=\"hljs-keyword\">const<\/span> Locale(<span class=\"hljs-string\">'en'<\/span>, <span class=\"hljs-string\">'US'<\/span>),\n      ],\n   ...\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-38\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Maintenant, l&rsquo;application affiche la ressource appropri\u00e9e pour les param\u00e8tres r\u00e9gionaux de l&rsquo;utilisateur et montre une solution de secours en cas de non prise en charge de ses param\u00e8tres r\u00e9gionaux. <!-- notionvc: 11d89077-09d6-4de7-9bed-5fc1c4306970 --><\/p>\n\n\n\n<figure class=\"wp-block-image wp-image-69078 size-full\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-69078 size-full\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/10\/computer-science-hero-demo-app-screen.png\" alt=\"\u00c9cran de l&apos;application de d\u00e9monstration montrant la ressource appropri\u00e9e pour les param\u00e8tres r\u00e9gionaux de l&apos;utilisateur et une solution de secours en cas de non prise en charge de ses param\u00e8tres r\u00e9gionaux | Phrase\" width=\"600\" height=\"301\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/10\/computer-science-hero-demo-app-screen.png 600w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/10\/computer-science-hero-demo-app-screen-300x151.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"changer-la-langue-dans-lapplication\"><\/span>Changer la langue dans l\u2019application<!-- notionvc: 9d86816e-04be-46f7-a903-fcb6f0d3bae1 --><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Parfois, un utilisateur voudra avoir son syst\u00e8me d&rsquo;exploitation dans une langue et une application sp\u00e9cifique, dans une autre. Pour pr\u00e9voir cette \u00e9ventualit\u00e9, ajoutons un s\u00e9lecteur de langue dans notre application. Cela fonctionne normalement pour toutes les plateformes prises en charge par Flutter. <!-- notionvc: 9444f110-143a-471a-955f-a1a9bba64d3b --><\/p>\n\n\n\n<figure class=\"wp-block-image size-full wp-image-69084\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-69084 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/10\/in-app-language.png\" alt=\"\u00c9cran de l&apos;application de d\u00e9monstration montrant les langues int\u00e9gr\u00e9es \u00e0 l&apos;application | Phrase\" width=\"341\" height=\"480\" srcset=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/10\/in-app-language.png 341w, https:\/\/phrase.com\/wp-content\/uploads\/2023\/10\/in-app-language-213x300.png 213w\" sizes=\"auto, (max-width: 341px) 100vw, 341px\" \/><\/figure>\n\n\n\n<p>Dans le fichier <code>main.dart<\/code>, nous allons apporter les modifications suivantes\u00a0:<\/p>\n\n\n\n<p><!-- notionvc: 0530a815-e9ef-468c-8f66-36c065263ac7 --><\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-39\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\"><span class=\"hljs-keyword\">void<\/span> main() {\n  runApp(<span class=\"hljs-keyword\">const<\/span> MyApp());\n}\n\n<span class=\"hljs-comment\">\/\/ We need to make MyApp Stateful because<\/span>\n<span class=\"hljs-comment\">\/\/ it needs to react when the Locale changes.<\/span>\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">MyApp<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatefulWidget<\/span> <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> MyApp({Key? key}) : <span class=\"hljs-keyword\">super<\/span>(key: key);\n\n  <span class=\"hljs-meta\">@override<\/span>\n  State&lt;MyApp&gt; createState() =&gt; _MyAppState();\n\n  <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> setLocale(BuildContext context, Locale newLocale) {\n    _MyAppState? state = context.findAncestorStateOfType&lt;_MyAppState&gt;();\n    state?.setLocale(newLocale);\n  }\n}\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">_MyAppState<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">State<\/span>&lt;<span class=\"hljs-title\">MyApp<\/span>&gt; <\/span>{\n  Locale? _locale;\n\n  setLocale(Locale locale) {\n    setState(() {\n      _locale = locale;\n    });\n  }\n\n  <span class=\"hljs-comment\">\/\/ This widget is the root of your application.<\/span>\n  <span class=\"hljs-meta\">@override<\/span>\n  Widget build(BuildContext context) {\n\n    <span class=\"hljs-keyword\">return<\/span> MaterialApp(\n      <span class=\"hljs-comment\">\/\/ ...<\/span>\n      locale: _locale,\n      initialRoute: <span class=\"hljs-string\">'\/'<\/span>,\n      routes: {\n        <span class=\"hljs-string\">'\/'<\/span>: (context) {\n          <span class=\"hljs-keyword\">return<\/span> HeroList(title: AppLocalizations.of(context)!.appTitle);\n        },\n      },\n    );\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-39\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>Maintenant, dans le fichier <code>hero_list.dart<\/code>, cr\u00e9ons le menu d\u00e9roulant et appelons la m\u00e9thode <code>setLocale()<\/code> que nous avons d\u00e9finie ci-dessus.<\/p>\n\n\n\n<p><!-- notionvc: a23338ef-f12b-4f8c-a1ac-fc207a9d47b9 --><\/p>\n\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-40\" data-shcb-language-name=\"Dart\" data-shcb-language-slug=\"dart\"><span><code class=\"hljs language-dart\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter\/material.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'package:flutter_gen\/gen_l10n\/app_localizations.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'..\/main.dart'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'..\/widgets\/hero_card.dart'<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HeroList<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">StatelessWidget<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n  <span class=\"hljs-meta\">@override<\/span>\n  Widget build(BuildContext context) {\n    <span class=\"hljs-keyword\">var<\/span> t = AppLocalizations.of(context)!;\n    <span class=\"hljs-keyword\">final<\/span> Locale locale = Localizations.localeOf(context);\n    <span class=\"hljs-comment\">\/\/ Dropdown options<\/span>\n    <span class=\"hljs-keyword\">var<\/span> items = &#91;\n      <span class=\"hljs-string\">'en'<\/span>,\n      <span class=\"hljs-string\">'ar'<\/span>,\n    ];\n\n    <span class=\"hljs-keyword\">return<\/span> Scaffold(\n      appBar: AppBar(\n        title: Text(title),\n        actions: &lt;Widget&gt;&#91;\n          DropdownButton(\n            <span class=\"hljs-comment\">\/\/ Down Arrow Icon<\/span>\n            icon: <span class=\"hljs-keyword\">const<\/span> Icon(Icons.settings, color: Colors.white,),\n            items: items.map((<span class=\"hljs-built_in\">String<\/span> items) {\n              <span class=\"hljs-keyword\">return<\/span> DropdownMenuItem(\n                value: items,\n                child: Text(items),\n              );\n            }).toList(),\n            onChanged: (<span class=\"hljs-built_in\">String<\/span>? newValue) {\n              MyApp.setLocale(context, Locale(newValue));\n            },\n          ),\n        ],\n      ),\n      <span class=\"hljs-comment\">\/\/ ...<\/span>\n    );\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-40\"><span class=\"shcb-language__label\">Langage du code\u00a0:<\/span> <span class=\"shcb-language__name\">Dart<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dart<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n\n<p>D\u00e9sormais, l&rsquo;utilisateur peut s\u00e9lectionner la langue de l\u2019application ind\u00e9pendamment de la langue du syst\u00e8me.<\/p>\n\n\n\n<p>\ud83d\uddd2\ufe0f <em>Remarque \u00bb<\/em> Avant que des param\u00e8tres r\u00e9gionaux ne soient s\u00e9lectionn\u00e9s, ils seront d\u00e9finis sur les param\u00e8tres r\u00e9gionaux par d\u00e9faut du syst\u00e8me de l\u2019utilisateur.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full wp-image-69090\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-69090 aligncenter\" src=\"https:\/\/phrase.com\/wp-content\/uploads\/2023\/10\/simulator-screen-recording-iphone-14-plus.gif\" alt=\"Enregistrement d&apos;\u00e9cran de l&apos;application simulateur sur iPhone 14 Plus | Phrase\" width=\"296\" height=\"640\" \/><\/figure>\n\n\n\n<p>\ud83d\uddd2\ufe0f <em>Remarque \u00bb<\/em> Avant que l&rsquo;utilisateur ne s\u00e9lectionne manuellement des param\u00e8tres r\u00e9gionaux dans l&rsquo;application, les param\u00e8tres r\u00e9gionaux du syst\u00e8me sont utilis\u00e9s par d\u00e9faut. Cependant, les param\u00e8tres linguistiques s\u00e9lectionn\u00e9s manuellement par l&rsquo;utilisateur dans l&rsquo;application <strong>ne seront pas conserv\u00e9s<\/strong> au red\u00e9marrage de l&rsquo;application. Pour conserver les param\u00e8tres r\u00e9gionaux pr\u00e9f\u00e9r\u00e9s de l&rsquo;utilisateur dans l&rsquo;application, vous devez les enregistrer et les r\u00e9cup\u00e9rer en utilisant par exemple le <a href=\"https:\/\/pub.dev\/packages\/shared_preferences\">plug-in Shared Preferences<\/a>.<\/p>\n\n\n\n<p>Le projet final est disponible sur <a href=\"https:\/\/github.com\/PhraseApp-Blog\/flutter-i18n-v2\">GitHub<\/a>.<\/p>\n\n\n\n<p><!-- notionvc: e6fc0d1e-c22a-45b2-8816-ef3f1c993cdc --><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"simplifier-la-localisation-du-contenu-flutter\"><\/span>Simplifier la localisation du contenu Flutter<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Nous esp\u00e9rons que vous avez appr\u00e9ci\u00e9 ce tutoriel consacr\u00e9 \u00e0 la localisation du contenu Flutter et que vous avez appris quelques astuces pratiques. Si vous \u00eates pr\u00eat \u00e0 passer au niveau sup\u00e9rieur en mati\u00e8re de localisation, <a href=\"https:\/\/phrase.com\/fr\/platform\/strings\/\">Phrase Strings<\/a> est votre solution de r\u00e9f\u00e9rence. V\u00e9ritable assistant de localisation pour vos applications Flutter, Phrase Strings prend en charge les fichiers ARB et se r\u00e9v\u00e8le tr\u00e8s convivial pour les d\u00e9veloppeurs gr\u00e2ce \u00e0 son API et \u00e0 son CLI faciles \u00e0 utiliser. Il dispose \u00e9galement d&rsquo;un \u00e9diteur de cha\u00eenes performant qui facilite consid\u00e9rablement le travail de traduction.<\/p>\n\n\n\n<p>De plus, il se synchronise parfaitement avec GitHub, GitLab et Bitbucket, et propose m\u00eame des traductions over-the-air pour les applications mobiles afin d&rsquo;all\u00e9ger la charge li\u00e9e \u00e0 la localisation, vous permettant de rester concentr\u00e9 sur ce qui compte le plus pour vous\u00a0: le code. D\u00e9couvrez toutes les <a href=\"https:\/\/phrase.com\/fr\/roles\/developers\/\">fonctionnalit\u00e9s de Phrase pour les d\u00e9veloppeurs<\/a> et comment elles peuvent vous aider \u00e0 internationaliser plus rapidement vos applications.<\/p>\n\n\n\n<p><!-- notionvc: 23cc7d5c-db75-40d3-a597-92c2e44cb6b5 --><\/p>\n\n\n\n<p><!-- notionvc: 91de31c5-0f6d-40c2-9d94-f70620d96540 --><\/p>\n\n\n","protected":false},"excerpt":{"rendered":"<p>D\u00e9codons ensemble les secrets de la localisation Flutter afin que vous permettre de parler la langue de vos utilisateurs et de continuer \u00e0 coder votre chemin vers le succ\u00e8s \u00e0 l&rsquo;international.<\/p>\n","protected":false},"author":41,"featured_media":2612,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"post-refresh-updated","format":"standard","meta":{"_acf_changed":false,"_stopmodifiedupdate":false,"_modified_date":"","_searchwp_excluded":"","episode_type":"","audio_file":"","podmotor_file_id":"","podmotor_episode_id":"","cover_image":"","cover_image_id":"","duration":"","filesize":"","filesize_raw":"","date_recorded":"","explicit":"","block":"","itunes_episode_number":"","itunes_title":"","itunes_season_number":"","itunes_episode_type":"","footnotes":""},"categories":[2459],"class_list":["post-133367","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-localisation-de-logiciels-fr"],"acf":[],"_links":{"self":[{"href":"https:\/\/phrase.com\/fr\/wp-json\/wp\/v2\/posts\/133367","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/phrase.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/phrase.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/phrase.com\/fr\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/phrase.com\/fr\/wp-json\/wp\/v2\/comments?post=133367"}],"version-history":[{"count":4,"href":"https:\/\/phrase.com\/fr\/wp-json\/wp\/v2\/posts\/133367\/revisions"}],"predecessor-version":[{"id":136293,"href":"https:\/\/phrase.com\/fr\/wp-json\/wp\/v2\/posts\/133367\/revisions\/136293"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/phrase.com\/fr\/wp-json\/wp\/v2\/media\/2612"}],"wp:attachment":[{"href":"https:\/\/phrase.com\/fr\/wp-json\/wp\/v2\/media?parent=133367"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/phrase.com\/fr\/wp-json\/wp\/v2\/categories?post=133367"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}