4

ローカライズされたブログ アプリでデータを構造化するのに苦労しています。

私のアプリは、埋め込み画像 (1 対多) を含む投稿を 3 つの言語 (英語、フランス語、ロシア語) で表示しています。

訪問者はロケールを選択できます。編集者は、ローカライズ版の投稿を 3 つの言語で編集できます。

現時点では、私のストアの構造は次のようになります。

{ 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 に対応します。

3 つの言語すべてに適用されるストアの変更がある場合 (たとえば、記事を削除した場合、その記事はすべての言語で削除する必要があります)現在、ローカライズされたサブ辞書とすべての補助ストアのサブ辞書 (「editStateOfFieldsOfArticles」など) に対して for...in を実行する必要があります (このような補助辞書は他にもいくつかあります)。

ただし、ハッシュをさらにフラット化することで他の利点が実際に得られるかどうかは完全にはわかりません (また、管理する言語が 3 つしかないため、for...in ループはそれほど問題ではありません。さらに、私のユースケースでは、記事を削除する必要があり、この削除を 3 つの言語すべてに反映する必要がある場合、フラット化された記事の辞書内の対応する 3 つのレコードを削除するには、3 つの言語配列を反復処理する必要があります)。

また、パフォーマンスの問題も懸念しています。(記事やその他の国際化されたアイテムの) コレクション全体を同じフラット ツリーの下に格納するので、関連する言語が何であれ、値へのアクセスがローカライズされたブランチを「サブキー化」することでアイテムにアクセスできる、より構造化されたツリーに-そして実際のところ、バックエンドデータベースはローカライズされた記事を個別のローカライズされたテーブルに保存します)。

国際化されたコンテンツ用の Redux ストアや複雑な相互関係を持つ他のストアを構築した経験のある人に、次の点に関するフィードバックやアドバイス、ヒントを提供してくれる人に本当に感謝しています。メモ化されたセレクター - ネストされたツリーとフラット ツリーのパフォーマンスの比較 - さらに正規化することと、ネストの「ビット」を維持することの全体的な利点。

4

1 に答える 1

0

このパーティーには大遅刻ですが、まだ興味がある場合に備えて。

あなたの最初の実装は間違いなく優れていると思います。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を使用してルックアップをキャッシュし、ロケールを組み込んだ再利用可能なルックアップ関数を作成できます。

于 2016-09-18T04:19:34.910 に答える