Remote Config Device Language Changes in Flutter
Solution 1
Device language changes can be detected using a WidgetsBindingObserver
.
It is the simplest to use it with a StatefulWidget
in your State
(with WidgetsBindingObserver
):
class _MyWidgetState extends State<MyWidget> with WidgetsBindingObserver {
@override
void didChangeLocales(List<Locale> locale) {
// The device language was changed when this is called.
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
...
}
This means that you can now reload your RemoteConfig
in didChangeLocales
:
@override
void didChangeLocales(List<Locale> locale) {
_updateRemoteConfig();
}
Future<void> _updateRemoteConfig() async {
final remoteConfig = await RemoteConfig.instance;
await remoteConfig.activateFetched(); // This will apply the new locale.
}
Solution 2
No there's no Builder
for Locale
.
Instead, there's an InheritedWidget
which you can subscribe to using Localizations.of
.
Since it is an InheritedWidget
, all widgets that call Localizations.of
will automatically refresh on locale change.
EDIT :
A example on how to live reload text using Flutter Locale system :
Let's assume you have the following class that holds translations :
class MyData {
String title;
MyData({this.title});
}
You'd then have a LocalizationsDelegate
that contains such data. A dumb implementation would be the following :
class MyLocale extends LocalizationsDelegate<MyData> {
MyData data;
MyLocale(this.data);
@override
bool isSupported(Locale locale) {
return true;
}
@override
Future<MyData> load(Locale locale) async {
return data;
}
@override
bool shouldReload(MyLocale old) {
return old.data != data;
}
}
To use it simply pass it to MaterialApp.localizationsDelegates
(be sure to add flutter_localizations
to your pubspec.yaml
) :
LocalizationsDelegate myLocale = MyLocale(MyData(title: "Foo"));
...
MaterialApp(
localizationsDelegates: [
myLocale,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
);
You can then freely live reload your translations by replacing myLocale
with a new MyLocale
instance.
Here's a full example of a click counter app. But where the current count is instead stored inside Locale
(because why not ?)
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
class MyCount {
String count;
MyCount({this.count});
}
class MyCountLocale extends LocalizationsDelegate<MyCount> {
MyCount data;
MyCountLocale(this.data);
@override
bool isSupported(Locale locale) {
return true;
}
@override
Future<MyCount> load(Locale locale) async {
return data;
}
@override
bool shouldReload(MyCountLocale old) {
return old.data != data;
}
}
Future<void> main() async {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
ValueNotifier<int> count = ValueNotifier<int>(0);
LocalizationsDelegate myLocale;
@override
void initState() {
count.addListener(() {
setState(() {
myLocale = MyCountLocale(MyCount(count: count.value.toString()));
});
});
myLocale = MyCountLocale(MyCount(count: count.value.toString()));
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [
myLocale,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
home: MyHomePage(count: count),
);
}
}
class MyHomePage extends StatefulWidget {
final ValueNotifier<int> count;
MyHomePage({this.count});
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
primary: true,
appBar: AppBar(),
body: Column(
children: <Widget>[
FloatingActionButton(
onPressed: () => widget.count.value++,
child: Icon(Icons.plus_one),
),
ListTile(
title: Text(Localizations.of<MyCount>(context, MyCount).count),
),
],
),
);
}
}
![creativecreatorormaybenot](https://i.stack.imgur.com/EIh1y.png?s=256&g=1)
creativecreatorormaybenot
Updated on December 05, 2022Comments
-
creativecreatorormaybenot over 1 year
I am encountering a problem, where localization works fine, but the applications needs to be restarted in order for the changes to propagate.
Orientation changes
I know about
OrientationBuilder
, which will call its builder whenever it detects a change in the device's orientation, which in e.g. Android would be considered as a configuration change, just like device language changes.Language changes
Is there something like
LanguageBuilder
? I could not find anything on my own and not on flutter.io nor on pub. I have read this tutorial and know aboutLocale
, but I do not see aStream
forLocale
.My problem is that changing the language in iOS and Android native is really smooth. It gets handled automatically and perfectly integrates with services like Firebase Remote Config.
I really wonder if there is some method that will allow me to refresh my localization.
Question
So I am asking how I can refresh my Remote Config when the device language changes.
-
user482594 over 4 yearsHello, did you get a chance to solve this problem?
-
creativecreatorormaybenot over 4 years@user482594 Yes, see my new answer.
-
-
Rémi Rousselet about 6 yearsWhen you call
Localization.of(context, type)
, this method will make thatcontext
rebuild whenever the associated locale change -
Rémi Rousselet about 6 yearsIf you don't know what
InheritedWidget
are, they are typically used to bind aBuildContext
to a data and force it to reload on change. WhereInheritedWidget
is the holder of that data. -
Bostrot about 6 yearsYou may want to have a look into this. It includes a nice example on how to use the InheritedWidget with
updateShouldNotify
. -
Rémi Rousselet almost 6 yearsAdded an example. Go take a look :)
-
Rémi Rousselet almost 6 yearsHere I made a dumb example where your
Locale
handle all languages at once. Although you could have multiplemyLocale
each handling a different language usingisSupported
method (and load your confs usingload
method) -
Rémi Rousselet almost 6 yearsMaybe make a question just your actual remote config setup. Dunno what can I add here.
-
creativecreatorormaybenot over 4 yearsTaking a look at my new answer, you might see why I thought that your answer was not a good answer to the question.
-
Fatima ayaa about 3 yearsis it detectable when I change the language outside the app means in the phone settings ?