データ (UI ではない) を国際化する必要がある i18n 要件に出くわします。
public class FooEntity
{
public long Id { get; set; }
public string Code { get; set; } // Some values might not need i18n
public string Name { get; set } // but e.g. this needs internationalized
public string Description { get; set; } // and this too
}
私が使用できるいくつかのアプローチは何ですか?
私が試したいくつかのこと:-
1)リソースキーをデータベースに保存します
public class FooEntity
{
...
public string NameKey { get; set; }
public string DescriptionKey { get; set; }
}
- 長所: 翻訳されたエンティティを取得するための複雑なクエリは必要ありません。
System.Globalization
フォールバックを処理します。 - 短所: 翻訳は、管理者ユーザーが簡単に管理することはできません (リソース ファイルを
Foo
変更するたびにデプロイする必要があります)。
2)LocalizableString
エンティティ タイプを使用する
public class FooEntity
{
...
public int NameId { get; set; }
public virtual LocalizableString Name { get; set; }
public int NameId { get; set; }
public virtual LocalizableString Description { get; set; }
}
public class LocalizableString
{
public int Id { get; set; }
public ICollection<LocalizedString> LocalizedStrings { get; set; }
}
public class LocalizedString
{
public int Id { get; set; }
public int ParentId { get; set; }
public virtual LocalizableString Parent { get; set; }
public int LanguageId { get; set; }
public virtual Language Language { get; set; }
public string Value { get; set; }
}
public class Language
{
public int Id { get; set; }
public string Name { get; set; }
public string CultureCode { get; set; }
}
- 長所: 同じテーブル内のすべてのローカライズされた文字列。検証は文字列ごとに実行できます。
- 短所: クエリは恐ろしいものです。親エンティティのローカライズ可能な文字列ごとに、LocalizedStrings テーブルを 1 回含める必要があります。フォールバックは難しく、大規模な参加が必要です。テーブルのデータなどを取得するときに N+1 を回避する方法が見つかりませんでした。
3) すべての不変プロパティを持つ親エンティティと、すべてのローカライズされたプロパティを含む子エンティティを使用する
public class FooEntity
{
...
public ICollection<FooTranslation> Translations { get; set; }
}
public class FooTranslation
{
public long Id { get; set; }
public int ParentId { get; set; }
public virtual FooEntity Parent { get; set; }
public int LanguageId { get; set; }
public virtual Language Language { get; set; }
public string Name { get; set }
public string Description { get; set; }
}
public class Language
{
public int Id { get; set; }
public string Name { get; set; }
public string CultureCode { get; set; }
}
- 長所: エンティティをメモリに完全に変換することはそれほど難しくありません (それでも難しすぎます!)。
- 短所: エンティティの数が 2 倍になります。エンティティの部分的な翻訳を処理できません。特に、 Name は from
es
ですが、 Description は fromの場合es-AR
です。
ソリューションには 3 つの要件があります
ユーザーは実行時にエンティティ、言語、および翻訳を編集できます
ユーザーは、System.Globalization に従って、フォールバックからの文字列が欠落している部分的な翻訳を提供できます。
N+1 の問題などに遭遇することなく、エンティティをメモリに取り込むことができます。