Lukas Nevosad
Lukas Nevosad

Reputation: 294

How do I programatically change Locale in Flutter when using MaterialApp.router()

I have:

final themeMode = context.select<PreferencesChangeNotifier, ThemeMode>((notifier) => notifier.themeMode);
final locale = context.select<LocaleChangeNotifier, Locale>((notifier) => notifier.locale);

return MaterialApp.router(
  locale: locale,
  debugShowCheckedModeBanner: false,
  scaffoldMessengerKey: MyApp.rootScaffoldMessengerKey,
  localizationsDelegates: AppLocalizations.localizationsDelegates,
  supportedLocales: AppLocalizations.supportedLocales,
  routeInformationParser: _routeInformationParser,
  routerDelegate: _routerDelegate,
  title: 'MyApp',
  theme: AppTheme.instance.lightTheme,
  darkTheme: AppTheme.instance.darkTheme,
  themeMode: themeMode,
);

But this only sets the initial Locale and even though MaterialApp gets rebuilt when locale changes, it does not reflect the change.

According to the docs, this is done using Localizations.override()

But I cannot put Localizations.override() above the MaterialApp, since localizations are not in its BuildContext.

I am completely lost where should I set the desired locale. The only thing I could think of is to override the locale on each screen, which seems hacky and I assume two sets of localizations would need to be loaded in such case.

Upvotes: 0

Views: 510

Answers (2)

Lukas Nevosad
Lukas Nevosad

Reputation: 294

Answering myself with a workaround to the problem, I am still looking for a better solution:

I wrapped the MaterialApp widget with a key dependent on Locale, so that the MaterialApp effectively restarts when the Locale changes:

final locale = context.select<LocaleChangeNotifier, Locale>((notifier) => notifier.locale);
return KeyedSubtree(
  key: Key('myApp-$locale'),
  child: MaterialApp.router(...),
);

I then had to add a locale dependent key to a few other places as some widgets persisted and got reattached to the new MaterialApp tree. It's a bit fragile solution, but seems to work for now.

Upvotes: 0

WizardKing
WizardKing

Reputation: 202

MaterialApp maybe not rebuilding when value of locale changes.

use a ValueListenableBuilder that listens to changes in the locale value and then rebuilds a materialApp

return ValueListenableBuilder<Locale>(
 valueListenable: locale,
 builder: (context, locale, _) {
   return MaterialApp.router(
     locale: locale,
     debugShowCheckedModeBanner: false,
     scaffoldMessengerKey: MyApp.rootScaffoldMessengerKey,
     localizationsDelegates: AppLocalizations.localizationsDelegates,
     supportedLocales: AppLocalizations.supportedLocales,
     routeInformationParser: _routeInformationParser,
     routerDelegate: _routerDelegate,
     title: 'MyApp',
     theme: AppTheme.instance.lightTheme,
     darkTheme: AppTheme.instance.darkTheme,
     themeMode: themeMode,
   );
 },
);

Upvotes: 1

Related Questions