Flutter 中的远程配置设备语言更改

Remote Config Device Language Changes in Flutter

我遇到了一个问题,本地化工作正常,但应用程序需要 重新启动 才能更改 propagate .

方向改变

我知道 OrientationBuilder,它会在检测到设备的 方向 发生变化时调用其构建器,例如Android 将被视为 配置 更改,就像设备语言更改一样。

语言变化

有没有类似LanguageBuilder的东西?我自己找不到任何东西,在 flutter.io nor on pub. I have read this tutorial 上也找不到任何东西,我知道 Locale,但我没有看到 LocaleStream

我的问题是在 iOSAndroid 中更改语言非常顺利。它会自动处理并与 Firebase Remote Config.

等服务完美集成

我真的很想知道是否有某种方法可以让我刷新我的本地化。

问题

所以我想问如何在设备语言更改时刷新我的远程配置

不,Locale没有Builder

相反,有一个 InheritedWidget,您可以使用 Localizations.of 订阅它。

因为它是 InheritedWidget,所有调用 Localizations.of 的小部件将在区域设置更改时自动刷新。

编辑 :

有关如何使用 Flutter Locale 系统实时重新加载文本的示例:

假设您有以下 class 包含翻译:

class MyData {
  String title;

  MyData({this.title});
}

然后您将拥有一个包含此类数据的 LocalizationsDelegate。一个愚蠢的实现如下:

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;
  }
}

要使用它,只需将它传递给 MaterialApp.localizationsDelegates(一定要将 flutter_localizations 添加到您的 pubspec.yaml):

LocalizationsDelegate myLocale = MyLocale(MyData(title: "Foo"));
...


MaterialApp(
  localizationsDelegates: [
    myLocale,
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
  ],
);

然后您可以通过将 myLocale 替换为新的 MyLocale 实例来自由地实时重新加载您的翻译。

这是点击计数器应用程序的完整示例。但是当前计数存储在 Locale 中(因为为什么不呢?)

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),
          ),
        ],
      ),
    );
  }
}

设备语言更改 可以使用 WidgetsBindingObserver.

检测到

在你的State(with WidgetsBindingObserver)中加上StatefulWidget是最简单的:

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();
  }
  ...
}

这意味着您现在可以重新加载您的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.
}