まず、制限を十分に認識してください。ユーザーが作成したコンテンツの場合、ユーザーがアプリケーションに入力するものをローカライズしたい場合は、コミュニティ翻訳 (不安定)、機械翻訳 (信頼性が低い)、または有償の人間の翻訳者 (高額!) を検討しています。デフォルト カルチャ (英語?) 用とローカライズされたカルチャ用の 2 つのバージョンを提供するようにユーザーに依頼したい場合があります。これにより、他のユーザーにフォールバック翻訳を提供できます。
第二に、非常に長いデータベースの移行に備えてください... Excel スプレッドシートに 4 列のテキストがある場合、突然、各値を翻訳システムに挿入し、ローカライズされた ID を取得して、それを保存する必要があります。実際にインポートしているテーブルではSELECT *
、翻訳テーブルに対してローカライズして文字列に戻す必要があるフレーズ ID のみが提供されます。
とはいえ、典型的なプロジェクトでデータベースによって駆動される多くのルックアップ テーブル、ドロップダウン リストなどをローカライズできます。他のコメントでは、外部リソース ファイルまたはスプレッドシートを参照する StringId 値をデータベースに保存することについて既に言及されていますが、ローカライズされたすべてのテキストをデータ自体と一緒にデータベースに保持することに関心がある場合は、このアプローチが役立つことがあります。
Phrase という名前のテーブルを使用しました。このテーブルには、アプリケーション内のすべてのテキストの ID とデフォルト (英語) のコンテンツが含まれています。
他のテーブルは次のようになります。
CREATE TABLE ProductType (
Id int primary key,
NamePhraseId int, -- link to the Phrase containing the name of this product type.
DescriptionPhraseId int
)
サポートしている特定のニュートラル カルチャを含む 2 番目のテーブル Culture を作成します。ボーナス ポイントとして、このテーブルを自己参照ツリーとして実装します (各カルチャ レコードには null 許容の ParentCultureCode 参照が含まれます)。これにより、特定のカルチャ (カナダ フランス語の「fr-CA」) からニュートラル カルチャ (「fr」) にフォールバックできます。地域のローカリゼーションが存在しない場合)、不変/既定のカルチャ (通常は「en」が広く使用されているため)
実際の翻訳は、次のような LocalizedPhrase テーブルにあります。
CREATE TABLE LocalizedPhrase (
PhraseId int primary key,
CultureCode varchar(8) primary key,
Content nvarchar(255) -- the actual localized content
)
男性/女性固有のローカライズを提供する場合は、このモデルを拡張できます。
CREATE TABLE GenderedLocalizedPhrase (
PhraseId int primary key,
CultureCode varchar(8) primary key,
GenderCode char(1) primary key, -- 'm', 'f' or '?' - links to Gender table
Content nvarchar(255)
)
このテーブル グラフ全体をメモリにキャッシュし、それに応じてクエリ/結合戦略を変更する必要があります。Phrase クラス内にローカリゼーションをキャッシュし、Phrase オブジェクトの ToString() メソッドをオーバーライドして現在のスレッド カルチャを検査するのが 1 つの方法です。クエリ内でこれを実行しようとすると、かなりのパフォーマンス コストが発生し、すべてのクエリが次のようになります。
-- assume @MyCulture contains the culture code ('ca-FR') that we are looking for:
SELECT
Product.Id,
Product.Name,
COALESCE(ProductStatusLocalizedPhrase.Content, ProductStatusPhrase.Content) as ProductStatus,
COALESCE(ProductTypeLocalizedPhrase.Content, ProductTypePhrase.Content) as ProductType,
FROM Product
INNER JOIN ProductStatus ON Product.StatusId = ProductStatus.Id
INNER JOIN Phrase as ProductStatusPhrase ON ProductStatus.NamePhraseId = Phrase.Id
LEFT JOIN LocalizedPhrase as ProductStatusLocalizedPhrase
ON ProductStatus.NamePhraseId = ProductStatusLocalizedPhrase.Id and CultureCode = @MyCulture
INNER JOIN ProductType ON Product.TypeId = ProductType.Id
INNER JOIN Phrase as ProductTypePhrase ON ProductType.NamePhraseId = Phrase.Id
LEFT JOIN LocalizedPhrase as ProductTypeLocalizedPhrase
ON ProductType.NamePhraseId = ProductTypeLocalizedPhrase.Id and CultureCode = @MyCulture