Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remote Config Device Language Changes in Flutter

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 about Locale, but I do not see a Stream for Locale.

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.

like image 660
creativecreatorormaybenot Avatar asked Dec 17 '25 23:12

creativecreatorormaybenot


1 Answers

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),
          ),
        ],
      ),
    );
  }
}
like image 135
Rémi Rousselet Avatar answered Dec 20 '25 14:12

Rémi Rousselet



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!