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

Mysql 保存多语言数据的最佳数据库结构是什么?,mysql,database,localization,translation,multilingual,Mysql,Database,Localization,Translation,Multilingual,可能重复: 下面是一个例子: [ 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 ] i

可能重复:

下面是一个例子:

[ 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)
问题是:每种新语言都需要创建新表,并且每个表中的price字段都是重复的

下面是另一个例子:

[ 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)

问题:难吗?

您的第三个示例实际上就是解决问题的方法。很难,但可行

从翻译表中删除对产品的引用,并将对翻译的引用放在需要它的地方

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

有多对多的关系

您有数据表、语言表和数据语言表

在data_language表中

id、数据id、语言id


我想这可能对你的工作最有利

为了减少联接的数量,您可以在两个单独的表中分别保存已翻译和未翻译的联接:

[ products ]
id (INT)
price (DECIMAL)

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

我们每天在webiste 600k的浏览量中使用了这个概念,也许令人惊讶的是,它确实有效。当然还有缓存和查询优化

[attribute_names]
id (INT)
name (VARCHAR)

[languages_names]
id (INT)
name (VARCHAR)

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

在我的$DAYJOB中,我们将gettext用于I18N。我编写了一个插件,从数据库表中提取所有英文文本,并将它们添加到master messages.pot

它工作得很好-译者在翻译时只处理一个文件-po文件。在进行翻译时,不能篡改数据库条目。

类似于方法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后缀的表,该后缀保存已翻译的字段。 当您从产品中选择*时,只需。。。在products\u t.id=products.id和products\u t.language=CURRENT\u语言上左键连接products\u t

没那么难,而且让你免于头痛。

[语言] id int PK 代码varchar

[products]
id (int PK)
name
price
all other fields of product
id_language ( int FK )
我实际上使用了这种方法,但在我的例子中,它不是从产品的角度来看的,对于我的CMS中的各种页面,这项工作非常好


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

第四个解决方案呢

[ products ]
id (INT)
language (VARCHAR 2)
name (VARCHAR)
description (VARCHAR)
price (DECIMAL)
*translation_of (INT FK)*
**的翻译是它自身的FK。添加默认语言时,*translation_of*设置为空。但是,当您添加第二语言时,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'

我们唯一的产品是波兰语翻译的。没有第二个表和联接。

@AntonioCS-数据表不是产品表,对吗?@TiuTalk是。这样,产品表不必知道有哪些语言,语言表也不必知道。都在数据语言表或本例中的“产品语言表”上第三种方法或多或少是正确的-有什么困难吗?问题是,在您找到的每个解决方案中,当您需要修改表时,您总会找到一个案例-即更多语言、不同语言,另一个领域…由于用户一次很可能只使用一种语言,我认为应该考虑为每种语言建立单独的数据库。这种方法将占用更多的存储空间,但是,它不会带来性能问题,而且设置起来也相对容易。@Clément-这里的问题是当products表获得一个新字段时。。。我还需要更改产品表:/@TiuTalk-表中只有一个将获得新字段,如果它是已翻译的字段,它将进入products_i18n,否则将进入products。这样您就不会复制任何信息。@Clément:product.id是products_i18n.id中的用户作为FK还是使用第三个联接表?@CoR Yes,products.id可以是products_i18n表中的foregin键。products_i18n表的主键将是一个由product.id、product_i18n.lang_代码组成的复合键。重复的字段(如price)如何?如果product表包含多个已翻译的字段怎么办?检索产品时,您必须为每个已翻译的字段执行一个附加联接,这将导致严重的性能问题。插入/更新/删除也有额外的复杂性。这样做的唯一优点是表的数量较少。我赞成吉卜赛·金或克莱门特提出的方法:我认为这是性能、复杂性和维护问题之间的良好平衡。这是一种有趣的方法。我喜欢查询的简单性,但它打破了产品表中的任何条目都是一个产品的假设,因此必须记住这一点。它还允许您继续对字段使用正确的类型varchar等。我现在正考虑实现完全相同的功能,但在其他任何地方都没有找到这种解决方案。我知道你的帖子是2011年的。你对此有什么问题吗?你还记得吗
墨水这是个好办法吗?谢谢。1它允许您同时拥有可翻译和不可翻译字段;2它不会将您的所有翻译绑定到默认语言的特定翻译;为了回答您的问题,插入、更新和删除都做得很好。问题全在我的脑子里-我知道数据库不是它应该的样子,这让我很烦。如果你只想为你的应用程序提供翻译,这可能会起作用。F.ex。菜单项、标题、帮助文本等。