保留多语言数据的最佳数据库结构是什么?

时间:2010-02-09 09:31:14

标签: mysql database localization translation multilingual

  

可能重复:
  Schema for a multilanguage database

以下是一个例子:

[ products ]
id (INT)
name-en_us (VARCHAR)
name-es_es (VARCHAR)
name-pt_br (VARCHAR)
description-en_us (VARCHAR)
description-es_es (VARCHAR)
description-pt_br (VARCHAR)
price (DECIMAL)

问题:每种新语言都需要修改表格结构。

这是另一个例子:

[ products-en_us ]
id (INT)
name (VARCHAR)
description (VARCHAR)
price (DECIMAL)

[ products-es_es ]
id (INT)
name (VARCHAR)
description (VARCHAR)
price (DECIMAL)

问题:每种新语言都需要创建新表格,每个表格中都会复制“价格”字段。

这是另一个例子:

[ languages ]
id (INT)
name (VARCHAR)

[ products ]
id (INT)
price (DECIMAL)

[ translation ]
id (INT, PK)
model (VARCHAR) // product
field (VARCHAR) // name
language_id (INT, FK) 
text (VARCHAR)

问题:很难?

8 个答案:

答案 0 :(得分:36)

与方法3类似:

[languages]
id (int PK)
code (varchar)

[products]
id (int PK)
neutral_fields (mixed)

[products_t]
id (int FK)
language (int FK)
translated_fields (mixed)
PRIMARY KEY: id,language

因此,对于每个表,创建另一个表(在我的情况下带有“_t”后缀),其中包含已翻译的字段。 当您SELECT * FROM products时,只需... LEFT JOIN products_t ON products_t.id = products.id AND products_t.language = CURRENT_LANGUAGE

不那么难,让你免于头痛。

答案 1 :(得分:28)

你的第三个例子实际上是解决问题的方式。很难,但可行。

从翻译表中删除对产品的引用,并在您需要的地方提供翻译参考(反之亦然)。

[ products ]
id (INT)
price (DECIMAL)
title_translation_id (INT, FK)

[ translation ]
id (INT, PK)
neutral_text (VARCHAR)
-- other properties that may be useful (date, creator etc.)

[ translation_text ]
translation_id (INT, FK)
language_id (INT, FK) 
text (VARCHAR)

作为替代方案(不是特别好的方法),您可以拥有一个单独的字段,并将所有翻译合并在一起(例如,XML)。

<translation>
  <en>Supplier</en>
  <de>Lieferant</de>
  <fr>Fournisseur</fr>
</translation>

答案 2 :(得分:13)

为了减少JOIN的数量,您可以将翻译和非翻译分开保存在两个单独的表中:

[ products ]
id (INT)
price (DECIMAL)

[ products_i18n ]
id (INT)
name (VARCHAR)
description (VARCHAR)
lang_code (CHAR(5))

答案 3 :(得分:3)

在我的$ DAYJOB中,我们使用gettext for I18N。我写了一个插件到xgettext.pl,它从数据库表中提取所有英文文本,并将它们添加到主消息.pot。

效果很好 - 翻译人员在翻译时只处理一个文件 - po文件。在进行翻译时,没有摆弄数据库条目。

答案 4 :(得分:2)

[语言]     id(int PK)     代码(varchar)

[products]
id (int PK)
name
price
all other fields of product
id_language ( int FK )

我实际上使用这种方法,但就我而言,它不是从产品的角度来看,对于CMS中的各种页面,这项工作非常好。

如果你有很多产品,用5或6种语言更新一个产品可能会很头疼......但这是一个处理布局的问题。

答案 5 :(得分:0)

第四种解决方案呢?

[ products ]
id (INT)
language (VARCHAR 2)
name (VARCHAR)
description (VARCHAR)
price (DECIMAL)
*translation_of (INT FK)*

* Translation_of *是 FK 的自我。当您添加默认语言* translation_of *设置为Null时。但是当你添加第二语言* translation_of *需要主要产品语言ID。

SELECT * FROM products WHERE id = 1 AND translation_of = 1

在这种情况下,我们会获得ID为1的产品的所有翻译。

SELECT * FROM products WHERE id = 1 AND translation_of = 1 AND language = 'pl'

我们只获得波兰语翻译产品。没有第二张桌子和JOINS。

答案 6 :(得分:-1)

有多对多的关系。

您拥有数据表,语言表和data_language表。

在data_language表中,您有

  

id,data_id,language_id

我认为这可能最适合你。

答案 7 :(得分:-2)

我们将这个概念用于您的网站(每天600k次观看)和(可能令人惊讶的)它的工作原理。当然还有缓存和查询优化。

[attribute_names]
id (INT)
name (VARCHAR)

[languages_names]
id (INT)
name (VARCHAR)

[products]
id (INT)
attr_id (INT)
value (MEDIUMTEXT)
lang_id (INT)