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

时间:2019-06-19 20:18:01

标签: flutter dart

我发现使用the official Flutter localization plugin很麻烦。要显示本地化的字符串,我必须调用Localization.of(context).myAppTitle-在具有大量本地化字符串的巨大嵌套小部件树中,它并不是完全圆滑或容易浏览。更不用说它看起来丑陋了。

有没有一种方法可以使用法更好?例如,是否可以将全局变量或静态类与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((){}); 
        });
    }
}

那我可以简单地打电话

Text(l.myAppTitle)

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

如果确实需要使用.of(BuildContext)方法来访问Localization实例-是否可以至少将其存储在StatefulWidget中?我在想类似的东西

class DetailsPage extends StatefulWidget{
    Localization _l;

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

        // ... build widgets ...
    }
}

还是有其他方法可以减少本地化的麻烦?

3 个答案:

答案 0 :(得分:1)

是的,这是必需的。 您可以解决它,但这是一个坏主意。

这样做的原因是Localization.of<T>(context, T)可能会随着时间更新。确实有以下几种情况:

  • 语言环境已更改
  • 获得的LocalizationsDelegate已异步加载
  • MaterialApp / CupertinoApp已更新为新翻译版本

如果您没有按照需要在 build 内部正确调用Localization.of,则在这些情况下,您的UI可能无法正确更新。

答案 1 :(得分:0)

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

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

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

  return Text(l.myAppTitle);
}

StatefulWidget中,您也可以在didChangeDependencies中重新分配变量,或者仅使用具有null感知功能的??=赋值一次,因为对象不会随着时间变化:

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

didChangeLocales中,您可以每次重新分配。这样可以确保变量始终保持适当的语言环境,并在首次构建时使用didChangeDependencies进行初始化。请注意,我还包括一个WidgetsBindingObserver,您需要按照代码中的说明进行处理。

答案 2 :(得分:0)

您可以创建自己的文本小部件并在那里进行本地化。您可以将所有文本小部件替换为自己的MyText小部件。

class MyText extends StatelessWidget {
  String data;
  InlineSpan textSpan;
  TextStyle style;
  StrutStyle strutStyle;
  TextAlign textAlign;
  TextDirection textDirection;
  Locale locale;
  bool softWrap;
  TextOverflow overflow;
  double textScaleFactor;
  int maxLines;
  String semanticsLabel;
  TextWidthBasis textWidthBasis;

  MyText(
    this.data, {
    Key key,
    this.style,
    this.strutStyle,
    this.textAlign,
    this.textDirection,
    this.locale,
    this.softWrap,
    this.overflow,
    this.textScaleFactor,
    this.maxLines,
    this.semanticsLabel,
    this.textWidthBasis,
  });

  @override
  Widget build(BuildContext context) {
    return Text(
      Localization.of(context).data,
      style: style,
      semanticsLabel: semanticsLabel,
      locale: locale,
      key: key,
      textAlign: textAlign,
      maxLines: maxLines,
      overflow: overflow,
      softWrap: softWrap,
      strutStyle: strutStyle,
      textDirection: textDirection,
      textScaleFactor: textScaleFactor,
      textWidthBasis: textWidthBasis,
    );
  }
}