9

我希望我的数据库支持其表中所有文本值的多语言。

那么最好的方法是什么?

编辑1::

例如

我有这个“人”表:

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
...........

或者我应该添加 2 个新表,一个用于语言,另一个用于“Person_Languages”值?

所以这看起来像:“语言”表:

ID           int
Lang-symbol  nvarchar(4)

”表:

ID         int
BirthDate  Date

最后是“ Person_Translation ”表:

LangID        int
PersonID      int
Translation   nvarchar(max)

还是有更好的东西??

.

4

2 回答 2

9

我不得不在问卷数据库中处理这个问题。多个问卷需要翻译成多种语言(英语、日语、中文)。

我们首先确定了将打印在问卷上的所有文本列。对于所有这些,我们需要能够存储翻译。对于每个包含需要翻译的文本列的表,然后我们创建了一个 _translations 表,其中有一个指向原始表主键的外键、一个指向我们的语言表的外键,然后每个文本字段都有一个 unicode 列那需要翻译。在这些文本列中,我们将存储我们需要的每种语言的翻译。

所以一个典型的查询看起来像:

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

因此,总是只有一个额外的连接(对于每个表)来获取翻译。

我应该指出,我们只需要处理有限数量的表,因此维护一些额外的 %_translations 表并不是什么大问题。

我们确实考虑为新语言添加列,但出于几个原因决定不这样做。首先,不知道要支持的语言数量,但可能很多(10 种、20 种或更多)。结合大多数表格至少有 3 个不同的人类可读列的事实,我们将不得不添加许多文本列,这将导致非常宽的行。所以我们决定不这样做。

我们考虑的另一种方法是制作一个大的“标签”表,其中包含以下列:

(table_name、id_of_table、column_name、language_id、translated_text)

有效地拥有一张表来存储数据库中任何位置的所有翻译。我们也决定不这样做,因为它会使编写查询复杂化(因为每个“正常”列都会在转换表中产生一行,这将导致有效地将已经很大的转换表多次连接到正常表(每个翻译的列)。对于您的示例表,您将获得如下查询:

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

如您所见,本质上类似于实体-属性-值设计,这使得查询起来很麻烦。

最后一种方法的另一个问题是,即使不是不可能,也很难对翻译文本实施约束(在我们的例子中主要是单一性约束)。使用单独的翻译表,您可以轻松干净地克服这些问题。

于 2009-12-30T13:46:49.523 回答
2

我刚刚实现了一些运行良好的东西。

像许多其他人一样,我一开始就没有一张白纸,所有的桌子都准备好存储英文文本。

我不是特别乐意将表或列的数量翻倍来实现多语言数据库。

我决定利用 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 {...}
}

这种方法使我不必完全重新划分数据库。这也意味着与数据库的交互更少,要保存一行而不是一个主行,以及 3 个翻译行。

它还避免了必须处理主行没有翻译行的情况的问题

应该注意的是,XML 有一个模式和 XML 索引来提高性能。

这种方法在您希望逐步进行语言转换(即一次一个字段)时非常有用。

于 2011-01-11T06:09:43.600 回答