Search code examples
flutterflutter-providerflutter-stateflutter-localizationsflutter-intl

Flutter - change locale and persisting with Provider


I am really out of options here. I am currently trying to have an option in my settings that enable the user to change language on a Button tap with Provider. Changing the language currently works just fine, but it is not persisted, because I am passing the provider locale to the locale in my MaterialApp:

 class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: providers,
      child: ChangeNotifierProvider(
        create:(_) => LocaleProvider(),
        builder: (context, child) {
          final provider = Provider.of<LocaleProvider>(context, listen: true);
          return MaterialApp(
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            initialRoute: '/',
            onGenerateRoute: RouteGenerator.generateRoute,
            localizationsDelegates: const [
              AppLocalizations.delegate,
              GlobalMaterialLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
              GlobalCupertinoLocalizations.delegate,
            ],
            supportedLocales: L10n.supportedLocales,
            locale: provider.locale,
          );
        },
      ),
    );
  }
}

My locale Provider currently looks like this:

class LocaleProvider extends ChangeNotifier {
  Locale _locale = const Locale('de');
  Locale get locale => _locale;

  void setLocale(Locale locale) async {
    _locale = await saveLocale(locale.languageCode);
    notifyListeners();
  }

The setLocale method is called from my Settings. I tried using sharedPreferences to store my locale, the Problem I have here is that I cannot call an async method on the locale property in the MaterialApp to await the value stored in sharedPreferences. What I want to achieve is, that the user can click on the button, the language gets changed instantly and is then saved and persisted until the user changes it again or uninstalls the app. Any help would be much appreciated here.


Solution

  • Of course, after posting this question I found a solution myself...

    I am currently retrieving the SharedPreferences in my main function, and then passing them down to MyApp:

    final prefs = await SharedPreferences.getInstance();
    runApp(MyApp(prefs: prefs,));
    

    In the MaterialApp, locale is set as follows:

    locale: Locale(_prefs.getString('locale') ?? provider.locale.languageCode),
    

    This will ensure, that on App Startup the locale isnt null, because in the provider, the locale property is initialized with a default value.