【问题标题】:How to support Multi-Languages approach in DataBase Schema?如何在数据库模式中支持多语言方法?
【发布时间】:2010-12-31 02:44:59
【问题描述】:

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

那么最好的方法是什么?

Edit1::

例如

我有这个“人”表:

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

如果我希望我的程序支持新语言“让我们说法语”。

是否应该在每次添加新语言时添加新列? 所以我的“Person”表看起来像这样

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)

还是有更好的??

.

【问题讨论】:

  • 请澄清...您的意思是对于每一行中的每个文本字段,您都希望能够存储多种语言的翻译吗?我的意思是,Unicode 将简单地为大多数语言启用文本存储,但您仍然需要一个适当的结构来存储多个翻译。
  • 在下面查看我的答案。简而言之,我选择为每个需要翻译的表创建一个单独的表。如果您确定只需要支持两种左右的语言(想想像加拿大这样拥有固定数量的官方广泛使用的语言的国家),那么添加新列是一种有效的方法。对于应用程序中的一般多语言支持,我不推荐这种方法。
  • Wahid,你的答案满意吗?还是您还在寻找更多建议?
  • 其实我还在努力寻找更好的解决方案。如您所见,我正在应用此解决方案,但我对性能有疑问。我会接受您的回答,谢谢:)
  • Wahid,我很想听听您遇到的其他方法。

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


【解决方案1】:

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

我们首先确定了将打印在问卷上的所有文本列。对于所有这些,我们需要能够存储翻译。对于每个包含需要翻译的文本列的表,然后我们创建了一个 _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 个不同的人类可读列的事实,我们将不得不添加许多文本列,这将导致非常宽的行。所以我们决定不这样做。

我们考虑的另一种方法是制作一个具有列的大“标签”表:

( 表名 , id_of_table , 列名 , 语言标识 , 翻译文本)

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

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

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

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

【讨论】:

  • 为了将待翻译的文本从数据库中提取出来,以便我们对其进行翻译,最后将翻译后的文本重新插入数据库,我使用了 XML/XSLT: rpbouman.blogspot.com/search?q=php+japanese+xml 但也许在你的情况下,你可以在应用程序的设计中直接考虑翻译。
  • +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 索引来提高性能。

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

【讨论】:

  • 我也在看这个想法,但是你如何配置你的 ORM 工具(你使用 C# 吗?实体框架?)
猜你喜欢
  • 1970-01-01
  • 2011-03-05
  • 2011-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多