7

我正在使用 Localizely 的 Flutter Intl 插件来本地化我的应用程序。我为我想要的语言生成了 arb 文件并开始介绍翻译。

例如:

{
  "documentsSection": "All the documents",
  "favouritesSection": "Favourites",
  "newsSection": "News",
  "settingsSection": "Settings"
}

每次我想本地化我使用的文本时:

S.of(context).favouritesSection;

而且效果很好。

但是,当我有这样的列表时:

List<Strings> sectionTitles = ["documentsSection","favouritesSection","newsSection","settingsSection"]

我在一个像这样的 itemBuilder 循环中:

itemBuilder: (context, index) {
                  String sectionName = sectionTitles[index];
                  return Text(
                      S.of(context).sectionName,
                  ),
                },

显然这不起作用,因为“sectionName”不是 arb 文件中的键。但我认为代码表达了我想要实现的目标。可能有人可以帮助我。提前致谢。

4

2 回答 2

12

解决此问题的另一种方法是使用Select ICU 格式的消息。
请注意,此解决方案可能会引入一些约束,但另一方面,它更优雅。

字符串键声明:

"sectionTitles": "{section, select, documentsSection {Documents section} favouritesSection {Favourites section} newsSection {News section} settingsSection {Settings section} other {Section}}",
"@sectionTitles": {
  "placeholders": {
    "section": {}
  }
}

字符串键用法:

itemBuilder: (context, index) {
                  String sectionName = sectionTitles[index];
                  return Text(
                      S.of(context).sectionTitles(sectionName),
                  ),
                },
于 2020-06-08T15:14:10.743 回答
1

我认为有两种方法可以实现您想要的。

首先是创建一个将您映射sectionTitles到您的国际字符串的函数,如下所示:

  String getSectionTitle(BuildContext context, String title) {
    if (title == "documentsSection") {
      return S.of(context).documentsSection;
    } else if (title == "favouritesSection") {
      return S.of(context).favouritesSection;
    } else if (title == "newsSection") {
      return S.of(context).newsSection;
    } else if (title == "settingsSection") {
      return S.of(context).settingsSection;
    }
  }

并像这样使用:

...
itemBuilder: (context, index) {
  return Text(
    getSectionTitle(context, sectionTitles[index]),
  );
},
...

第二个是用你的 intl 字符串创建一个数组:

List<String> sectionTitles = [
      S.of(context).documentsSection,
      S.of(context).favouritesSection,
      S.of(context).newsSection,
      S.of(context).settingsSection,
];

但是您需要在构建函数中创建它,因为您需要一个上下文:

  @override
  Widget build(BuildContext context) {
    List<String> sectionTitles = [
      S.of(context).documentsSection,
      S.of(context).favouritesSection,
      S.of(context).newsSection,
      S.of(context).settingsSection,
    ];
    return ...
          itemBuilder: (context, index) {
            return Text(
              sectionTitles[index],
            );
          },
    ...
  }

在不使用构建函数的上下文的情况下实现此目的的另一种方法是使用didChangeDependencieson 可用的方法StatefulWidgets,如下所示:

 List<String> sectionTitles;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    sectionTitles ??= [
      S.of(context).documentsSection,
      S.of(context).favouritesSection,
      S.of(context).newsSection,
      S.of(context).settingsSection,
    ];
  }

  @override
  Widget build(BuildContext context) {
    return ...       
          itemBuilder: (context, index) {
            return Text(
              sectionTitles[index],
            );
          },
    ...
  }

请注意,在这种情况下,您不能使用initState,因为它不会提供已经可用的 intl 字符串的上下文,因此我们使用didChangeDependencies.

如果你想知道它做了什么??=,它只是检查一个变量(在这种情况下sectionTitles)是否为空,如果是,它会将值分配给它。我们在这里使用它来避免sectionTitles每次都重新定义。

于 2020-06-07T02:59:28.650 回答