Flutter - Internationalisation

De nos jours, les applications mobiles sont utilisées par des clients de différents pays et, par conséquent, les applications doivent afficher le contenu dans différentes langues. Permettre à une application de fonctionner dans plusieurs langues s'appelle Internationaliser l'application.

Pour qu'une application fonctionne dans différentes langues, elle doit d'abord trouver les paramètres régionaux actuels du système dans lequel l'application s'exécute, puis afficher son contenu dans ces paramètres régionaux particuliers, et ce processus est appelé Localisation.

Le framework Flutter fournit trois classes de base pour la localisation et des classes utilitaires étendues dérivées de classes de base pour localiser une application.

Les classes de base sont les suivantes -

  • Locale - Locale est une classe utilisée pour identifier la langue de l'utilisateur. Par exemple, en-us identifie l'anglais américain et peut être créé comme.

Locale en_locale = Locale('en', 'US')

Ici, le premier argument est le code de langue et le deuxième argument est le code du pays. Un autre exemple de création de paramètres régionaux en Argentine (es-ar) est le suivant:

Locale es_locale = Locale('es', 'AR')
  • Localisations - Localisations est un widget générique utilisé pour définir les paramètres régionaux et les ressources localisées de son enfant.

class CustomLocalizations { 
   CustomLocalizations(this.locale); 
   final Locale locale; 
   static CustomLocalizations of(BuildContext context) { 
      return Localizations.of<CustomLocalizations>(context, CustomLocalizations); 
   } 
   static Map<String, Map<String, String>> _resources = {
      'en': {
         'title': 'Demo', 
         'message': 'Hello World' 
      }, 
      'es': {
         'title': 'Manifestación', 
         'message': 'Hola Mundo', 
      }, 
   }; 
   String get title { 
      return _resources[locale.languageCode]['title']; 
   }
   String get message { 
      return _resources[locale.languageCode]['message']; 
   } 
}
  • Ici, CustomLocalizations est une nouvelle classe personnalisée créée spécifiquement pour obtenir certains contenus localisés (titre et message) pour le widget. of method utilise la classe Localizations pour renvoyer la nouvelle classe CustomLocalizations.

  • LocalizationsDelegate <T> - LocalizationsDelegate <T> est une classe d'usine à travers laquelle le widget Localisations est chargé. Il a trois méthodes excessivement ridables -

    • isSupported - Accepte une locale et retourne si la locale spécifiée est prise en charge ou non.

@override 
bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);

      Ici, le délégué fonctionne uniquement pour en et es locale.

    • load - Accepte un paramètre régional et commence le chargement des ressources pour le paramètre régional spécifié.

@override 
Future<CustomLocalizations> load(Locale locale) { 
   return SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale)); 
}

      Ici, la méthode load retourne CustomLocalizations. Les CustomLocalizations renvoyées peuvent être utilisées pour obtenir des valeurs de titre et de message en anglais et en espagnol

    • shouldReload - Spécifie si le rechargement de CustomLocalizations est nécessaire lorsque son widget Localisations est reconstruit.

@override 
bool shouldReload(CustomLocalizationsDelegate old) => false;
  • Le code complet de CustomLocalizationDelegate est le suivant -

class CustomLocalizationsDelegate extends 
LocalizationsDelegate<CustomLocalizations> { 
   const CustomLocalizationsDelegate(); 
   @override 
   bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);
   @override 
   Future<CustomLocalizations> load(Locale locale) { 
      return SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale));
   } 
   @override bool shouldReload(CustomLocalizationsDelegate old) => false; 
}

En général, les applications Flutter sont basées sur deux widgets de niveau racine, MaterialApp ou WidgetsApp. Flutter fournit une localisation prête à l'emploi pour les deux widgets et il s'agit de MaterialLocalizations et WidgetsLocaliations. En outre, Flutter fournit également des délégués pour charger MaterialLocalizations et WidgetsLocaliations et ils sont respectivement GlobalMaterialLocalizations.delegate et GlobalWidgetsLocalizations.delegate.

Créons une application simple permettant l'internationalisation pour tester et comprendre le concept.

  • Créez une nouvelle application de flutter, flutter_localization_app.

  • Flutter prend en charge l'internationalisation en utilisant le package flutter exclusif, flutter_localizations. L'idée est de séparer le contenu localisé du SDK principal. Ouvrez le pubspec.yaml et ajoutez le code ci-dessous pour activer le package d'internationalisation -

dependencies: 
   flutter: 
      sdk: flutter 
   flutter_localizations:
      sdk: flutter
  • Le studio Android affichera l'alerte suivante indiquant que pubspec.yaml est mis à jour.

  • Cliquez sur l'option Obtenir les dépendances. Le studio Android obtiendra le package sur Internet et le configurera correctement pour l'application.

  • Importez le package flutter_localizations dans le main.dart comme suit -

import 'package:flutter_localizations/flutter_localizations.dart'; 
import 'package:flutter/foundation.dart' show SynchronousFuture;
  • Ici, le but de SynchronousFuture est de charger les localisations personnalisées de manière synchrone.

  • Créez une localisation personnalisée et son délégué correspondant comme spécifié ci-dessous -

class CustomLocalizations { 
   CustomLocalizations(this.locale); 
   final Locale locale; 
   static CustomLocalizations of(BuildContext context) {
      return Localizations.of<CustomLocalizations>(context, CustomLocalizations); 
   }
   static Map<String, Map<String, String>> _resources = {
      'en': {
         'title': 'Demo', 
         'message': 'Hello World' 
      }, 
      'es': { 
         'title': 'Manifestación', 
         'message': 'Hola Mundo', 
      }, 
   }; 
   String get title { 
      return _resources[locale.languageCode]['title']; 
   } 
   String get message { 
      return _resources[locale.languageCode]['message']; 
   } 
}
class CustomLocalizationsDelegate extends
LocalizationsDelegate<CustomLocalizations> {
   const CustomLocalizationsDelegate();
   
   @override 
   bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode); 
   
   @override 
   Future<CustomLocalizations> load(Locale locale) { 
      return SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale)); 
   } 
   @override bool shouldReload(CustomLocalizationsDelegate old) => false; 
}
  • Ici, CustomLocalizations est créé pour prendre en charge la localisation du titre et du message dans l'application et CustomLocalizationsDelegate est utilisé pour charger CustomLocalizations.

  • Ajoutez des délégués pour MaterialApp, WidgetsApp et CustomLocalization à l'aide des propriétés MaterialApp, localizationsDelegates et supportedLocales comme spécifié ci-dessous -

localizationsDelegates: [
   const CustomLocalizationsDelegate(),   
   GlobalMaterialLocalizations.delegate, 
   GlobalWidgetsLocalizations.delegate, 
], 
supportedLocales: [
   const Locale('en', ''),
   const Locale('es', ''), 
],
  • Utilisez la méthode CustomLocalizations, of pour obtenir la valeur localisée du titre et du message et utilisez-la à l'endroit approprié comme spécifié ci-dessous -

class MyHomePage extends StatelessWidget {
   MyHomePage({Key key, this.title}) : super(key: key); 
   final String title; 
   @override 
   Widget build(BuildContext context) {
      return Scaffold(
         appBar: AppBar(title: Text(CustomLocalizations .of(context) .title), ), 
         body: Center(
            child: Column(
               mainAxisAlignment: MainAxisAlignment.center, 
               children: <Widget>[ 
                  Text( CustomLocalizations .of(context) .message, ), 
               ], 
            ), 
         ),
      );
   }
}
  • Ici, nous avons modifié la classe MyHomePage de StatefulWidget à StatelessWidget pour des raisons de simplicité et utilisé les CustomLocalizations pour obtenir le titre et le message.

  • Compilez et exécutez l'application. L'application affichera son contenu en anglais.

  • Fermez l'application. Aller àSettings → System → Languages and Input → Languages*.

  • Cliquez sur Ajouter une option de langue et sélectionnez Espagnol. Cela installera la langue espagnole, puis la listera comme l'une des options.

  • Sélectionnez l'espagnol et déplacez-le au-dessus de l'anglais. Cela définira l'espagnol comme première langue et tout sera changé en texte espagnol.

  • Relancez maintenant l'application d'internationalisation et vous verrez le titre et le message en espagnol.

  • Nous pouvons rétablir la langue en anglais en déplaçant l'option anglais au-dessus de l'option espagnole dans le paramètre.

  • Le résultat de l'application (en espagnol) est montré dans la capture d'écran ci-dessous -

Utilisation du package intl

Flutter fournit un package intl pour simplifier davantage le développement d'applications mobiles localisées. Le paquet intl fournit des méthodes et des outils spéciaux pour générer semi-automatiquement des messages spécifiques à une langue.

Créons une nouvelle application localisée en utilisant le package intl et comprenons le concept.

  • Créez une nouvelle application de flutter, flutter_intl_app.

  • Ouvrez pubspec.yaml et ajoutez les détails du package.

dependencies: 
   flutter: 
      sdk: flutter 
   flutter_localizations: 
      sdk: flutter 
   intl: ^0.15.7 
   intl_translation: ^0.17.3
  • Le studio Android affichera l'alerte comme indiqué ci-dessous pour informer que pubspec.yaml est mis à jour.

  • Cliquez sur l'option Obtenir les dépendances. Le studio Android obtiendra le package sur Internet et le configurera correctement pour l'application.

  • Copiez le main.dart de l'exemple précédent, flutter_internationalization_app.

  • Importez le pacakge intl comme indiqué ci-dessous -

import 'package:intl/intl.dart';
  • Mettez à jour la classe CustomLocalization comme indiqué dans le code ci-dessous -

class CustomLocalizations { 
   static Future<CustomLocalizations> load(Locale locale) {
      final String name = locale.countryCode.isEmpty ? locale.languageCode : locale.toString(); 
      final String localeName = Intl.canonicalizedLocale(name); 
      
      return initializeMessages(localeName).then((_) {
         Intl.defaultLocale = localeName; 
         return CustomLocalizations(); 
      }); 
   } 
   static CustomLocalizations of(BuildContext context) { 
      return Localizations.of<CustomLocalizations>(context, CustomLocalizations); 
   } 
   String get title {
      return Intl.message( 
         'Demo', 
         name: 'title', 
         desc: 'Title for the Demo application', 
      ); 
   }
   String get message{
      return Intl.message(
         'Hello World', 
         name: 'message', 
         desc: 'Message for the Demo application', 
      ); 
   }
}
class CustomLocalizationsDelegate extends 
LocalizationsDelegate<CustomLocalizations> {
   const CustomLocalizationsDelegate();
   
   @override
   bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode); 
   @override 
   Future<CustomLocalizations> load(Locale locale) { 
      return CustomLocalizations.load(locale); 
   } 
   @override 
   bool shouldReload(CustomLocalizationsDelegate old) => false; 
}
  • Ici, nous avons utilisé trois méthodes du package intl au lieu de méthodes personnalisées. Sinon, les concepts sont les mêmes.

    • Intl.canonicalizedLocale - Utilisé pour obtenir le nom de locale correct.

    • Intl.defaultLocale - Utilisé pour définir les paramètres régionaux actuels

    • Intl.message - Utilisé pour définir de nouveaux messages.

  • importer l10n/messages_all.dartfichier. Nous allons générer ce fichier sous peu

import 'l10n/messages_all.dart';
  • Maintenant, créez un dossier, lib / l10n

  • Ouvrez une invite de commande et accédez au répertoire racine de l'application (où pubspec.yaml est disponible) et exécutez la commande suivante -

flutter packages pub run intl_translation:extract_to_arb --output-
   dir=lib/l10n lib/main.dart
  • Ici, la commande générera, fichier intl_message.arb, un modèle pour créer un message dans différents paramètres régionaux. Le contenu du fichier est le suivant -

{
   "@@last_modified": "2019-04-19T02:04:09.627551", 
   "title": "Demo", 
   "@title": {
      "description": "Title for the Demo application", 
      "type": "text", 
      "placeholders": {} 
   }, 
   "message": "Hello World", 
   "@message": {
      "description": "Message for the Demo 
      application", 
      "type": "text", 
      "placeholders": {} 
   }
}
  • Copiez intl_message.arb et créez un nouveau fichier, intl_en.arb.

  • Copiez intl_message.arb et créez un nouveau fichier, intl_es.arb et changez le contenu en espagnol comme indiqué ci-dessous -

{
   "@@last_modified": "2019-04-19T02:04:09.627551",  
   "title": "Manifestación", 
   "@title": {
      "description": "Title for the Demo application", 
      "type": "text", 
      "placeholders": {} 
   },
   "message": "Hola Mundo",
   "@message": {
      "description": "Message for the Demo application", 
      "type": "text", 
      "placeholders": {} 
   } 
}
  • Maintenant, exécutez la commande suivante pour créer le fichier de message final, messages_all.dart.

flutter packages pub run intl_translation:generate_from_arb 
--output-dir=lib\l10n --no-use-deferred-loading 
lib\main.dart lib\l10n\intl_en.arb lib\l10n\intl_es.arb
  • Compilez et exécutez l'application. Il fonctionnera de la même manière que l'application ci-dessus, flutter_localization_app.