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

To control the locale of the app, you can use the locale property of the MaterialApp:

return MaterialApp(
  ...
  locale: _myLocal,
  ...
);

This, combined with @ilikerobots StatefulWidget approach shall provide you with what you need.


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


using one of the Providers should do the job, I am not really familiar with providers but this got me working easily

  1. wrap your material app using ChangeNotifierProvider
    return ChangeNotifierProvider(
        create: (_) => new LocaleModel(),
        child: Consumer<LocaleModel>(
            builder: (context, provider, child) => MaterialApp(
                title: 'myapp',
                locale: Provider.of<LocaleModel>(context).locale
                 ...
                 ...
                 ...

  1. create A model class with getters and setters to get & set the locale as\
import 'package:iborganic/const/page_exports.dart';

class LocaleModel with ChangeNotifier {
  Locale locale = Locale('en');
  Locale get getlocale => locale;
  void changelocale(Locale l) {
    locale = l;
    notifyListeners();
  }
}

  1. Change the locale on some event (button click) as
Provider.of<LocaleModel>(context).changelocale(Locale("kn"));

The benefit of wrapping the material app within Provider is you can have access to the locale value from any part of your app

Tags:

Flutter