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
- creating a new LocalizationsDelegate that either translates to a single locale or defers completely depending on a parameter
- converting the base app (MyApp) to a stateful widget and inserting the new delegate above into the localizationsDelegates list
- 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
- 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
...
...
...
- 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();
}
}
- 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