我很难在本地化的博客应用程序中构建我的数据。
我的应用以三种语言(英语,法语和俄语)显示带有嵌入图片(一对多)的帖子。
访问者可以选择其语言环境。编辑可以用三种语言编辑其帖子的本地化版本。
目前,我店的结构如下:
{ 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},
...
}
}
“articles”,“pictures”和“editStatesOfFieldsOfArticles”词典的键的最后一位数字对应于locale / language_id,其他数字将对应于项目ID。
我看到当我有一个适用于所有三种语言的商店修改时(例如,如果我删除一篇文章,该文章应该删除)需要迭代语言,我将从这样一个更扁平的结构中受益删除所有三种语言,我目前必须在本地化的子词典和所有辅助商店的子词典(例如“editStateOfFieldsOfArticles”(我有一些其他这样的辅助词典))中进行操作。
然而,我并不完全确定我是否真的会从进一步展平我的哈希值中获得任何其他好处(并且for ... in循环不会出现问题,只需管理三种语言 - 此外,在我的使用中我需要删除一篇文章的情况,这个删除需要反映在所有三种语言中,我仍然需要迭代三种语言数组来删除展平文章字典中的三个相应记录。
另外,我关注性能问题:因为我将整个集合(文章或任何其他国际化项目)存储在相同的扁平树下,无论它们与哪种语言有关,我担心访问这些值可能与更结构化的树相比,我可以通过“子键控”本地化分支来访问项目,从而减慢速度 - 事实上,后端数据库将本地化文章存储在不同的本地化表中。
我真的很感谢有经验为国际化内容或其他具有复杂交叉关系的商店构建Redux商店的人,他们可以就自己的经验提供一些反馈或建议或提示: - 代码可读性,特别是在reducer和memoized选择器中, - 比较嵌套树与扁平树的表现, - 进一步规范化与保持“嵌套”的整体好处。
答案 0 :(得分:0)
这个派对已经很晚了,但万一你还好奇。
我认为你的第一次实施绝对是优越的。 for循环超过3个项目不是一个征税交易,你可以(并且应该)将其分解为辅助函数:
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来缓存查找并使重复使用的查找功能包含语言环境。