Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter: Multi-lingual application - how to override the locale?

Tags:

I followed the explanations given in the official Flutter pages (see here) to make my application work in different languages.

According to the documentation, it retrieves the user's locale and this works fine.

Let's now suppose that my application supports different languages (such as EN, FR, ES, ...) and that the user could select one of these languages to use the application (the selected language would then be different than the one defined in the phone's settings), how can I achieve this?

How may I force the application Locale and dynamically "reload" all the translations?

The Flutter page does not explain this and I haven't seen anything that help me in the documentation...

Here is the current implementation:

class Translations {   Translations(this.locale);    final Locale locale;    static Translations of(BuildContext context){     return Localizations.of<Translations>(context, Translations);   }    static Map<String, Map<String, String>> _localizedValues = {     'en': {       'title': 'Hello',     },     'fr': {       'title': 'Bonjour',     },     'es': {       'title': 'Hola',     }   };    String text(String key){     return _localizedValues[locale.languageCode][key] ?? '** ${key} not found';   } }  class TranslationsDelegate extends LocalizationsDelegate<Translations> {   const TranslationsDelegate();    @override   bool isSupported(Locale locale) => ['en', 'fr','es'].contains(locale.languageCode);    @override   Future<Translations> load(Locale locale) {     return new SynchronousFuture<Translations>(new Translations(locale));   }    @override   bool shouldReload(TranslationsDelegate old) => false; } 

In the main.dart:

class MyApp extends StatelessWidget {   @override   Widget build(BuildContext context) {     return new MaterialApp(       title: Translations.of(context).text('title'),       theme: new ThemeData(         primarySwatch: Colors.blue,       ),       localizationsDelegates: [         const TranslationsDelegate(),         GlobalMaterialLocalizations.delegate,         GlobalWidgetsLocalizations.delegate,       ],       supportedLocales: [         const Locale('en', ''), // English         const Locale('fr', ''), // French         const Locale('fr', ''), // French       ],         home: new LandingPage(),     );   } } 

Many thanks for your help.

like image 274
boeledi Avatar asked Mar 23 '18 01:03

boeledi


People also ask

How do you add multi language support to your Flutter app via dynamic localization?

You can add any number of language support by adding . arb files, the process for that is very simple. Just click on Tools > Flutter Intl > Add Locale.

How do you use multiple languages on Flutter app?

By default, Flutter only provides US English localizations. To add support for other languages, an application must specify additional MaterialApp (or CupertinoApp ) properties, and include a package called flutter_localizations . As of November 2020, this package supports 78 languages.


1 Answers

This can be accomplished by

  1. creating a new LocalizationsDelegate that either translates to a single locale or defers completely depending on a parameter
  2. converting the base app (MyApp) to a stateful widget and inserting the new delegate above into the localizationsDelegates list
  3. managing the base app (MyApp) state with a new delegate targeting a specific locale based on some event

A simple implementation for 1) might be:

class SpecifiedLocalizationDelegate     extends LocalizationsDelegate<Translations> {   final Locale overriddenLocale;    const SpecifiedLocalizationDelegate(this.overriddenLocale);    @override   bool isSupported(Locale locale) => overriddenLocale != null;    @override   Future<Translations> load(Locale locale) =>       Translations.load(overriddenLocale);    @override   bool shouldReload(SpecifiedLocalizationDelegate old) => true; } 

Next for 2) and 3), convert the MyApp to stateful and include the new delegate (initially just deferring everything), plus some event handlers to change the state with a new delegate that specifies a new Locale.

class MyApp extends StatefulWidget {   @override   _MyAppState createState() => new _MyAppState(); }  class _MyAppState extends State<MyApp> {   SpecifiedLocalizationDelegate _localeOverrideDelegate;    @override   void initState() {     super.initState();     _localeOverrideDelegate = new SpecifiedLocalizationDelegate(null);   }    onLocaleChange(Locale l) {     setState(() {       _localeOverrideDelegate = new SpecifiedLocalizationDelegate(l);     });   }    @override   Widget build(BuildContext context) {     return new MaterialApp(       localizationsDelegates: [         _localeOverrideDelegate,         const TranslationsDelegate(),         GlobalMaterialLocalizations.delegate,         GlobalWidgetsLocalizations.delegate,       ],       supportedLocales: [         const Locale('en', ''), // English         const Locale('fr', ''), // French       ],       home: new LandingPage(onLocaleSwitch: onLocaleChange),     );   } } 

With these changes, in children widgets you could now use Translations.of(context).myLocalizedString to retrieve the translations.

More complete gist: https://gist.github.com/ilikerobots/474b414138f3f99150dbb3d0cc4cc721

like image 79
ilikerobots Avatar answered Sep 29 '22 05:09

ilikerobots