构建本地化反应/冗余应用程序的存储

Structuring the store of a localized react / redux app

本文关键字:应用程序 存储 冗余 本地化 构建      更新时间:2023-09-26

我很难在本地化的博客应用程序中构建数据。

我的应用程序以三种语言(英语、法语和俄语)显示带有嵌入式图片(一对多)的帖子。

访问者可以选择其区域设置。编辑者可以用三种语言编辑其帖子的本地化版本。

目前,我的商店结构如下所示:

{ articles:
  {
    en: {
      1: { id: 1, title: "my first title", body: "my first body", picture_ids: [1, 2, 3]},
      2: { id: 2, title: "my second title", body: "my second body", picture_ids: [1, 4, 5]},
      3: { id: 3, title: "my third title", body: "my third body", picture_ids: [6, 7, 8]},
      ...
    },
    fr: {
      1: { id: 1, title: "mon premier titre", body: "mon premier corps de texte", picture_ids: [1, 2, 3]},
      2: { id: 2, title: "mon second titre", body: "mon second corps de texte", picture_ids: [1, 4, 5]},
      3: { id: 3, title: "mon troisième titre", body: "mon troisième corps de texte", picture_ids: [6, 7, 8]},
      ...
    }
  },
  pictures:
   {
      en: {
        1: { id: 1, title: "My great picture", url: "http://..."},
        2: { id: 2, title: "My other great picture", url: "http://..."},
        3: { id: 3, title: "My not so great picture", url: "http://..."},
        ...
      },
      fr: {
        1: { id: 1, title: "Ma superbe photo", url: "http://..."},
        2: { id: 2, title: "Mon autre superbe photo", url: "http://..."},
        3: { id: 3, title: "Ma photo pas vraiment superbe", url: "http://..."},
        ...
      }
   },
   editStateOfFieldsOfArticles:
   {
      en: {
        1: { title: true, body: false },
        2: { title: false, body: true },
        3: { title: false, body: false },
        ...
      },
      fr: {
        1: { title: false, body: false },
        2: { title: false, body: false },
        3: { title: true, body: true },
        ...
      }
   }
}

在这个阶段,我的化简器并不太臃肿,但我觉得我应该进一步规范化,以便预测何时添加与文章相关的标签、作者和其他国际化项目。

所以我正在考虑 (i) 在存储中为语言创建一个额外的词典,(ii) "扁平化"所有其他词典以摆脱"区域设置"子存储键,(iii) 在其他词典中存储的每个项目中添加一个language_id字段和 (iv) 将我每个词典中的数字键修改为组合键。这看起来像这样:

{languages:
  {
    1: {id: 1, locale: "en", long: "English"},
    2: {id: 2, locale: "fr", long: "Français"},
    3: {id: 3, locale: "ru", long: "русская"}
  }
  articles:
  {
    11: {id: 1, title: "my first title", body: "my first body", picture_ids: [1, 2, 3], language_id: 1},
    21: {id: 2, title: "my second title", body: "my second body", picture_ids: [1, 4, 5], language_id: 1},
    31: {id: 3, title: "my third title", body: "my third body", picture_ids: [6, 7, 8], language_id: 1},
    42: {id: 1, title: "mon premier titre", body: "mon premier corps de texte", picture_ids: [1, 2, 3], language_id: 2},
    52: {id: 2, title: "mon second titre", body: "mon second corps de texte", picture_ids: [1, 4, 5], language_id: 2},
    62: {id: 3, title: "mon troisième titre", body: "mon troisième corps de texte", picture_ids: [6, 7, 8], language_id: 2},
    ...
  },
  pictures:
  {
    11: {id: 1, title: "My great picture", url: "http://...", language_id: 1},
    21: {id: 2, title: "My other great picture", url: "http://...", language_id: 1},
    31: {id: 3, title: "My not so great picture", url: "http://...", language_id: 1},
    12: {id: 1, title: "Ma superbe photo", url: "http://...", language_id: 2},
    22: {id: 2, title: "Mon autre superbe photo", url: "http://...", language_id: 2},
    32: {id: 3, title: "Ma photo pas vraiment superbe", url: "http://...", language_id: 2},
    ...
  },
  editStateOfFieldsOfArticles:
  }
    11: {title: true, body: false, language_id: 1},
    21: {title: false, body: true, language_id: 1},
    31: {title: false, body: false, language_id: 1},
    12: {title: false, body: false, language_id: 2},
    22: {title: false, body: false, language_id: 2},
    32: {title: true, body: true, language_id: 2},
    ...
  }
}
"

文章"、"图片"和"editStatesOfFieldsOfArticles"词典的键的最后一位数字对应于区域设置/language_id,其他数字对应于项目 ID。

看到当我有适用于所有三种语言的商店修改时,我将从这种更扁平的结构中受益,摆脱迭代语言的需要(例如,如果我删除一篇文章,该文章应该删除所有三种语言,我目前必须做一个......在本地化的子词典和所有辅助存储的子词典上(例如"editStateOfFieldsOfArticles"(我还有其他一些这样的辅助词典))。

但是,我不完全确定我是否真的会从进一步扁平化我的哈希(以及 for...在只有三种语言需要管理的情况下,循环并不是那么成问题——此外,在我的用例中,我需要删除一篇文章并且这种删除需要反映在所有三种语言中,我仍然必须遍历三种语言数组以删除扁平化文章字典中的三个相应记录)。

此外,我担心

性能问题:由于我将把我的整个集合(文章或任何其他国际化项目)存储在同一个平面树下,无论它们与什么语言相关,我担心与更结构化的树相比,对这些值的访问可能会变慢,在这种树中,我可以通过"子键控"本地化分支来访问项目 - 事实上, 后端数据库将本地化的文章存储在不同的本地化表中)。

我非常感谢任何具有为国际化内容或其他具有复杂交叉关系的商店构建 Redux 商店经验的人,他们可以就自己的经验提供一些反馈、建议或提示:- 代码可读性,特别是在化简器和记忆选择器中,- 比较嵌套树与扁平树的性能,- 进一步规范化与保持嵌套"位"的总体好处。

这个派对超级晚了,但如果你仍然好奇。

我认为您的第一个实现绝对是优越的。 超过 3 个项目的 for 循环不是繁重的事务,您可以(并且应该)将其分解到帮助程序函数中:

var forEachLanguage = function(state, dataType, callback){
    var languages_data = state[dataType];
    for(language_index in languages_data){
        var data = languages_data[language_index];
        callback(data);
    }
}
//Example for deleting item 2 from articles
forEachLanguage(state, 'articles', function(data){
    delete data[2];
});

此外,如果您担心重复查找变得不必要地昂贵(尽管实际上,我认为这不是问题),您可以使用 Reselect 来缓存查找并制作包含区域设置的可重用查找函数。