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

发布于 2024-08-20 13:55:28 字数 984 浏览 5 评论 0原文

可能的重复:
多语言数据库架构

以下是一个示例:

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

问题:很难吗?

Possible Duplicate:
Schema for a multilanguage database

Here's an example:

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

The problem: every new language will need modify the table structure.

Here's another example:

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

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

The problem: every new language will need the creation of new tables and the "price" field is duplicated in every table.

Here's another example:

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

The problem: hard?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

能否归途做我良人 2024-08-27 13:55:28

与方法 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

没那么难,而且可以让你远离头痛。

Similar to method 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

So for each table, make another table (in my case with "_t" suffix) which holds the translated fields.
When you SELECT * FROM products, simply ... LEFT JOIN products_t ON products_t.id = products.id AND products_t.language = CURRENT_LANGUAGE.

Not that hard, and keeps you free from headaches.

葬シ愛 2024-08-27 13:55: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>

Your third example is actually the way the problem is usually solved. Hard, but doable.

Remove the reference to product from the translation table and put a reference to translation where you need it (the other way around).

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

As an alternative (not especially a good one) you can have one single field and keep all translations there merged together (as XML, for example).

<translation>
  <en>Supplier</en>
  <de>Lieferant</de>
  <fr>Fournisseur</fr>
</translation>
心清如水 2024-08-27 13:55:28

为了减少 JOIN 的数量,您可以将已翻译和未翻译的内容分开保存在 2 个单独的表中:

[ products ]
id (INT)
price (DECIMAL)

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

In order to reduce the number of JOIN's, you could keep separate the translated and non translated in 2 separate tables :

[ products ]
id (INT)
price (DECIMAL)

[ products_i18n ]
id (INT)
name (VARCHAR)
description (VARCHAR)
lang_code (CHAR(5))
错爱 2024-08-27 13:55:28

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

它工作得很好 - 翻译人员在翻译时只处理一个文件 - po 文件。进行翻译时无需修改数据库条目。

At my $DAYJOB we use gettext for I18N. I wrote a plugin to xgettext.pl that extracts all English text from the database tables and add them to the master messages.pot.

It works very well - translators deal with only one file when doing translation - the po file. There's no fiddling with database entries when doing translations.

浅沫记忆 2024-08-27 13:55:28

[语言]
id(整数PK)
code (varchar)

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

我实际上使用了这种方法,但就我而言,它不是从产品的角度来看,对于我的CMS中的各个页面来说,这种工作相当不错。

如果您有很多产品,那么用 5 或 6 种语言更新单个产品可能会很麻烦……但这是一个布局问题。

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

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

I actually use this method, but in my case, it's not in a product point of view, for the various pages in my CMS, this work's quite well.

If you have a lot of products it might be a headache to update a single one in 5 or 6 languages... but it's a question of working the layout.

衣神在巴黎 2024-08-27 13:55:28

那么第四个解决方案呢?

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

我们仅获得波兰语翻译的产品。没有第二个表和联接。

What about fourth solution?

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

*Translation_of* is FK of it self. When You add default language *translation_of* is set to Null. But when you add second language *translation_of* takes primary produkt language id.

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

In that case we get all translations for product with id is 1.

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

We get only product in Polish translation. Without second table and JOINS.

天荒地未老 2024-08-27 13:55:28

具有多对多的关系。

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

在 data_language 表中你有

id、data_id、语言_id

我认为这可能最适合您。

Have many to many relationship.

You have your data table, languages table and a data_language table.

In the data_language table you have

id, data_id, language_id

I think that might work best for your.

尬尬 2024-08-27 13:55:28

我们将这个概念用于我们的网站(每天 60 万次浏览)并且(也许令人惊讶)它确实有效。当然还有缓存和查询优化。

[attribute_names]
id (INT)
name (VARCHAR)

[languages_names]
id (INT)
name (VARCHAR)

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

We use this concept for our webiste (600k views per day) and (maybe surprisingly) it works. Sure along with caching and query optimalization.

[attribute_names]
id (INT)
name (VARCHAR)

[languages_names]
id (INT)
name (VARCHAR)

[products]
id (INT)
attr_id (INT)
value (MEDIUMTEXT)
lang_id (INT)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文