9

データベースで、テーブル内のすべてのテキスト値に対して複数の言語をサポートする必要があります。

それで、それを行うための最良のアプローチは何ですか?

Edit1 ::

例えば

私はこの「人」テーブルを持っています:

ID int
FirstName  nvarchar(20)
LastName   nvarchar(20)
Notes      nvarchar(max)
BirthDate  date
...........

したがって、プログラムで新しい言語「フランス語としましょう」をサポートしたい場合。

新しい言語を追加するたびに新しい列を追加する必要がありますか?だから私の「人」テーブルはこのようになります

ID int
FirstName_en  nvarchar(20)
FirstName_fr  nvarchar(20)
LastName_en   nvarchar(20)
LastName_fr   nvarchar(20)
Notes_en      nvarchar(max)
Notes_fr      nvarchar(max)
BirthDate     date
...........

または、言語用と「Person_Languages」値用の2つの新しいテーブルを追加する必要がありますか?

したがって、これは次のようになります。「言語」テーブル:

ID           int
Lang-symbol  nvarchar(4)

」テーブル:

ID         int
BirthDate  Date

そして最後に「Person_Translation」テーブル:

LangID        int
PersonID      int
Translation   nvarchar(max)

またはもっと良いものがありますか?

4

2 に答える 2

9

私はアンケートデータベースでこれに対処しなければなりませんでした。複数のアンケートを複数の言語 (英語、日本語、中国語) に翻訳する必要がありました。

最初に、アンケートに印刷されるすべてのテキスト列を特定しました。これらすべてについて、翻訳を保存できる必要があります。翻訳が必要なテキスト列を持つテーブルごとに、元のテーブルの主キーを指す外部キー、言語テーブルへの外部キー、および各テキスト フィールドの Unicode 列を持つ _translations テーブルを作成しました。それには翻訳が必要です。これらのテキスト列には、必要な各言語の翻訳を保存します。

したがって、典型的なクエリは次のようになります。

select     p.id
,          pt.product_name
,          pt.product_description
from       product                  p
inner join product_translations pt
on         p.id = pt.product_id
and        'fr' = pt.language_code

そのため、翻訳を取得するために、(テーブルごとに) 常に 1 つの追加の結合のみを行います。

限られた数のテーブルを処理するだけでよかったので、いくつかの追加の %_translations テーブルを維持することは大きな問題ではありませんでした。

新しい言語用に列を追加することも検討しましたが、いくつかの理由から断念しました。まず第一に、サポートされる言語の数は不明でしたが、かなりの数になる可能性があります (10、20、またはそれ以上の言語)。ほとんどのテーブルには少なくとも 3 つの個別の人間が読める列があるという事実と組み合わせると、非常に多くのテキスト列を追加する必要があり、結果として非常に幅の広い行になります。だから私たちはそれをしないことにしました。

列を持つ 1 つの大きな「ラベル」テーブルを作成するために検討した別のアプローチ:

( table_name 、 id_of_table 、 column_name 、 language_id 、translated_text)

データベース内の任意の場所にすべての翻訳を格納する 1 つのテーブルを効果的に持つ。クエリの作成が複雑になるため、これにも反対することにしました (「通常の」列ごとに変換テーブルに 1 つの行が作成され、すでに大きな変換テーブルが通常のテーブルに複数回 (それぞれに 1 回) 効果的に結合されるため)。例のテーブルでは、次のようなクエリが得られます。

select     product.id 
,          product_name.translated_text product_name
,          product_description.translated_text product_description
from       product p
inner join translations product_name
on         p.id = product_name.id
and        'product'      = product_name.table_name
and        'product_name' = product_name.column_name
and        'fr'           = product_name.language
inner join translations product_description
on         p.id = product_name.id
and        'product'      = product_description.table_name
and        'product_description' = product_description.column_name
and        'fr'           = product_description.language

ご覧のとおり、本質的にこの種のエンティティ属性値の設計に似ているため、クエリが煩雑になります。

最後のアプローチのもう 1 つの問題は、翻訳されたテキストに制約 (この場合は主に単一性制約) を適用することが不可能ではないにしても困難になることです。翻訳用の別のテーブルを使用すると、これらの問題を簡単かつきれいに克服できます。

于 2009-12-30T13:46:49.523 に答える
2

非常にうまく機能するものを実装しました。

他の多くの人と同じように、私は最初から白紙の状態ではなく、すべてのテーブルが英語のテキストを格納するように調整されていました。

多言語データベースを実現するために、テーブルまたは列の数を 2 倍にすることに特に満足していませんでした。

すべての翻訳を 1 つのフィールドに格納する方法として、XML を利用することにしました。

<text>
  <translation lang="EN-GB">good day</translation>
  <translation lang="FR-FR">bonjour</translation>
</text>

たとえば、英語のみを保持するテーブルから始めました。

ProductId INT
ProductName varchar(200)
ProductDescription varchar(1000)

次に、多言語フィールドを作成しました。

ProductId INT
ProductNameTranslation xml
ProductDescriptionTranslation xml

元のフィールドの読み取り専用値を取得できるようにする場合は、永続化された計算列を追加するだけです。

ProductId INT
ProductNameTranslation xml
ProductDescriptionTranslation xml
ProductNameDefaultLang = dbo.GetDefaultLanguage(ProductNameTranslation)
ProductDescriptionDefaultLang = dbo.GetDefaultLanguage(ProductDescriptionTranslation)

ビジネス/データ レイヤーでは、XML フィールドはディクショナリ タイプのビジネス クラスに変換され、キーは言語の列挙です。

ProductName {
  get {return this.ProductNameTranslation[selectedLanguage];}
  set {...}
}

このアプローチにより、データベースを完全に再分割する必要がなくなりました。また、データベースとのやり取りが少なくなり、1 つのメイン行ではなく 1 つの行が保存され、3 つの翻訳行が保存されます。

また、メイン行に翻訳行がない場合に処理しなければならないという問題を回避します。

パフォーマンスを向上させるために、XML にはスキーマと XML インデックスが含まれていることに注意してください。

このアプローチは、一度に 1 つのフィールドなど、段階的に言語変換を行いたい場合に非常に便利です。

于 2011-01-11T06:09:43.600 に答える