如何在DataBase Schema中支持多语言方法?

时间:2009-12-30 13:29:36

标签: database database-design localization globalization database-schema

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

那么最好的方法是什么?。

EDIT1 ::

  

E.G。

     

我有这个“人”表:

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)

还是有更好的东西?

2 个答案:

答案 0 :(得分: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

正如您所看到的,基本上这类似于实体属性值设计,这使得查询变得很麻烦。

最后一种方法的另一个问题是,如果不是不可能的话,对翻译文本强制执行约束(在我们的例子中主要是单一性约束)会很困难。通过单独的翻译表,您可以轻松,干净地克服这些问题。

答案 1 :(得分: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字段将转换为字典类型的业务类,其中key是语言枚举:

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

这种方法让我可以避免完全重新修复数据库。它还意味着与数据库的交互较少,要保存一行而不是一个主行,以及3个转换行。

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

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

如果您希望逐步进行语言转换(即一次一个字段),此方法非常有用。