无需每次都调用 `of(context)` 的本地化

Mag*_*s W 5 dart flutter

我发现使用官方 Flutter 本地化插件的本地化过程很麻烦。要显示我必须调用的本地化字符串Localization.of(context).myAppTitle- 在具有大量本地化字符串的巨大嵌套 Widget 树中并不完全光滑或易于浏览。更不用说它看起来很丑。

有没有办法让使用更好?例如,我可以使用全局变量或带有Localization实例成员的静态类来使访问更容易吗?例如声明一个顶级Localization变量

// Somewhere in the global scope
Localization l;


// main.dart
class _MyAppState extends State<MyApp>{

    @override
    void initState() {
        super.initState();
        getLocaleSomehow().then((locale){ 
            l = Localization(locale);
            setState((){}); 
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我可以简单地打电话

Text(l.myAppTitle)
Run Code Online (Sandbox Code Playgroud)

所以从本质上讲,我要问的是“不打电话有Localization.of(context)什么危险和/或缺点?”

如果我真的需要使用该.of(BuildContext)方法来访问Localization实例 - 我至少可以将它存储在我的StatefulWidget? 我在想像

class DetailsPage extends StatefulWidget{
    Localization _l;

    @override
    Widget build(BuildContext context) {
        _l = Localization.of(context);

        // ... build widgets ...
    }
}
Run Code Online (Sandbox Code Playgroud)

或者有没有其他方法可以让本地化不那么麻烦?

Feu*_*Feu 8

我将这里其他回复(特别是 Fleximex 的)的一些信息结合到一个我发现非常有趣的解决方案中 - 这就是我正在使用的解决方案。我在其本身上创建了一个扩展BuildContext

extension BuildContextHelper on BuildContext {
  AppLocalizations get l {
    // if no locale was found, returns a default
    return AppLocalizations.of(this) ?? AppLocalizationsEn();
  }
}
Run Code Online (Sandbox Code Playgroud)

使用此扩展(并导入它),可以像这样使用它:

context.l.appTitle
Run Code Online (Sandbox Code Playgroud)

或者

context.l.helloUser(name)
Run Code Online (Sandbox Code Playgroud)

恕我直言,它干净且可读,但它不是最短的。


Rém*_*let 6

是的,这是需要的。你可以解决这个问题,但这是一个坏主意。

其原因是Localization.of<T>(context, T)可能会随着时间的推移而更新。它的一些情况是:

  • 区域设置已更改
  • 获取到的LocalizationsDelegate是异步加载的
  • MaterialApp/CupertinoApp 已更新新翻译

如果您没有按照应有的方式正确调用Localization.of内部构建,那么在这些情况下您的 UI 可能无法正确更新。


cre*_*not 5

Localization将对象存储在您的内部是完全可以的State,并且在这种情况下效果非常好。

如果你只想让它看起来更好,你也可以在 build 方法中声明变量:

@override
Widget build(BuildContext context) {
  final l = Localization.of(context);

  return Text(l.myAppTitle);
}
Run Code Online (Sandbox Code Playgroud)

在 a 中,您还可以使用空感知运算StatefulWidget符重新分配变量 in或仅分配一次,因为对象不会随时间变化:didChangeDependencies??=

class _MyStatefulWidgetState extends State<MyStatefulWidget> with WidgetsBindingObserver {
  Localization l;

  @override
  didChangeDependencies() {
    WidgetsBinding.instance.addObserver(this);
    l ??= Localization.of(context);
    super.didChangeDependencies();
  }

  @override
  void didChangeLocales(List<Locale> locale) {
    l = Localization.of(context);
    super.didChangeLocales(locale);
  }

  @override
  dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => Text(l.myAppTite);
}
Run Code Online (Sandbox Code Playgroud)

在 中didChangeLocales,您每次都可以重新分配。这可确保变量始终保留适当的语言环境,并在第一次构建时进行初始化(使用didChangeDependencies)。请注意,我还包含了一个WidgetsBindingObserver,您需要按代码中所示处理它。