Dans la page des paramètres de mon application, je voudrais ajouter une option qui contrôle la langue de l'application.
Je peux définir la langue avant de démarrer l'application comme ceci:
@override Widget build(BuildContext context) { return MaterialApp( // other arguments locale: Locale('ar'), ); }
Mais est-il possible de changer la langue sans redémarrer l'application?
4 Réponses :
Enveloppez votre MaterialApp
dans un StreamBuilder
qui sera chargé de fournir la Locale
valeur à votre application. Et cela vous permettra de le changer dynamiquement sans redémarrer votre application. Voici un exemple utilisant le package rxdart pour implémenter le flux:
@override Widget build(BuildContext context) { return StreamBuilder( stream: setLocale, initialData: Locale('ar',''), builder: (context, localeSnapshot) { return MaterialApp( // other arguments locale: localeSnapshot.data, ); } ); } Stream<Locale> setLocale(int choice) { var localeSubject = BehaviorSubject<Locale>() ; choice == 0 ? localeSubject.sink.add( Locale('ar','') ) : localeSubject.sink.add( Locale('en','') ) ; return localeSubject.stream.distinct() ; }
La démonstration ci-dessus n'est qu'un moyen basique de savoir comment réaliser ce que vous voulez, mais pour une mise en œuvre correcte des flux dans votre application, vous devez envisager d'utiliser des BloC à l'échelle de l'application, ce qui améliorera considérablement la qualité de votre application en réduisant le nombre de builds inutiles.
mais le streamBuilder n'est pas reconstruit lorsque nous appelons setLocale depuis une autre partie de l'application
Vous pouvez encapsuler le widget MaterialApp
avec un ChangeNotifierProvider
et un widget Consumer
et contrôler la langue à partir du modèle.
@override Widget build(BuildContext context) { return ChangeNotifierProvider( builder: (context) => MainModel(context: context), child: Consumer<MainModel>(builder: (context, mainModel, child) { return MaterialApp( locale: Locale(mainModel.preferredLanguageCode), ....
Sur le MainModel
, tout ce que vous avez à faire est de changer la variable preferredLanguageCode
en ce que vous voulez ('en', 'ar', 'es', etc.). N'oubliez pas d'appeler NotifyListeners()
une fois que vous avez changé la langue.
Ceci et l'autre réponse n'ont qu'un seul problème: tout context
au-dessus de MaterialApp
ne peut pas obtenir la langue de l'appareil (par exemple lorsque l'application est démarrée pour la première fois) avec Localizations.localeOf(context)
. Cette méthode nécessitait un context
MaterialApp
.
Pour résoudre ce problème, j'ai utilisé ce plugin pour obtenir la langue de l'appareil sans avoir besoin d'un context
.
Une fois que l'application démarre, vous pouvez changer la langue comme vous le souhaitez pour que cette approche fonctionne. J'utilise également SharedPreferences
pour stocker la langue préférée une fois que l'utilisateur la modifie.
Si vous souhaitez changer la langue de l'application sans redémarrer l'application et également sans aucun plugin, vous pouvez suivre les étapes ci-dessous:
Dans le fichier principal de l'application, changez la MyHomePage
par défaut en StatefullWidget
, dans StatefullWedget
par exemple MyHomePage
créez une méthode static
setLocal
comme suit
Locale newLocale = Locale('ps', 'AFG'); MyHomePage.setLocale(context, newLocale);
où _MyHomePageState
est l' state
de votre widget MyHomePage
Dans votre state
créez un changeLanguage
méthode static
class _MyHomePageState extends State<MyHomePage> { Locale _locale; changeLanguage(Locale locale) { setState(() { _locale = locale; }); } @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Afghanistan', theme: ThemeData(primaryColor: Colors.blue[800]), supportedLocales: [ Locale('fa', 'IR'), Locale('en', 'US'), Locale('ps', 'AFG'), ], locale: _locale, localizationsDelegates: [ AppLocalizationsDelegate(), GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate ], localeResolutionCallback: (locale, supportedLocales) { for (var supportedLocale in supportedLocales) { if (supportedLocale.languageCode == locale.languageCode && supportedLocale.countryCode == locale.countryCode) { return supportedLocale; } } return supportedLocales.first; }, initialRoute: splashRoute, onGenerateRoute: Router.generatedRoute, ); } }
Maintenant, à partir des pages de votre application, vous pouvez changer la langue en appelant la méthode setLocal
et passer un nouveau Locale
comme suit:
class MyHomePage extends StatefulWidget { MyHomePage({Key key}) : super(key: key); static void setLocale(BuildContext context, Locale newLocale) async { _MyHomePageState state = context.findAncestorStateOfType<_MyHomePageState>(); state.changeLanguage(newLocale); } @override _MyHomePageState createState() => _MyHomePageState(); }
N'oubliez pas que vous devez créer un LocalizationDelegate
,
Voici le lien vers le didacticiel écrit et l'application de démonstration
Réponse très utile. Logique simple de flottement.
Il est plus facile d'utiliser le package easy_localization .
Pour changer de langue, par exemple:
onTap: (){ EasyLocalization.of(context).locale = Locale('en', 'US'); }
J'ai appris à utiliser ce package par cette vidéo: Youtube Video Link
Intéressant, je me souviens sur Android C'est assez compliqué de changer de langue sans perdre son état. Mais cela pourrait être fait.