数据库设计:如何支持多语言网站?

发布于 2024-10-30 13:24:36 字数 751 浏览 4 评论 0原文

假设我有这样的表格:

TABLE: product
=================================================================
| product_id | name           | description                     |
=================================================================
| 1          | Widget 1       | Really nice widget. Buy it now! |
-----------------------------------------------------------------

如果我想提供多语言支持,最好的方法是什么?

可能的解决方案:

  1. 在上表中添加“语言”列;这将指示特定记录的语言。 (我不认为这对我来说是一个选择,因为其他表将使用product.product_id作为其FK。)
  2. 删除product表中的任何可翻译列(在上面的示例中,product.name和product.description)并将其放入在带有“语言”列的单独表中。该新表将使用product.product_id 作为 FK。 (我不会在应用程序的第一个版本中支持多语言。此解决方案意味着我必须执行额外的 JOIN 才能获取最初支持的语言的值。)
  3. 还有什么我没有考虑的吗?

Suppose I have the table:

TABLE: product
=================================================================
| product_id | name           | description                     |
=================================================================
| 1          | Widget 1       | Really nice widget. Buy it now! |
-----------------------------------------------------------------

If I want to provide multi-lingual support, what's the best approach to do that?

Possible solutions:

  1. Add a "language" column to the above table; that'll indicate the language the particular record is. (I don't think this is an option for me since other tables will be using product.product_id as its FK.)
  2. Remove any translatable columns in product table (in the above example, product.name and product.description) and put it in a separate table with a "language" column. That new table will use product.product_id as a FK. (I won't be supporting multi-languages in the first version of my application. This solution means I would have to do an extra JOIN just to get the values of the initially supported language.)
  3. Something else that I didn't consider?

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

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

发布评论

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

评论(5

幽梦紫曦~ 2024-11-06 13:24:36

我会选择解决方案 2。

此选项将最大限度地减少您的第一个版本的工作,并将减少不更改的列之间的重复。

它确实需要额外的JOIN,但它是一个简单的键连接,因此不会对您的性能产​​生太大影响。

I would go with solution 2.

This option will minimize your work for your first version, and will reduce repetition between the columns that do not change.

It does require an extra JOIN, but it is a simple key join so it will not affect your performance much.

浮生未歇 2024-11-06 13:24:36

我会选择第三种替代方案,它是您现有设计和解决方案#2 的混合体。表中存在的列现在代表您的“中性”或默认语言。然后,您将为需要翻译值的每个实体添加一个表,其中包含主表的 PK、语言代码的键以及父表中需要翻译的每个值的列。因此,我们可能有

Create Table product_translations
    (
    product_id int not null References product( id )
    , language_code varchar(5) not null
    , name ...
    , description ...
    , Primary Key ( product_id, language_code )
    ...
    )

您的查询然后看起来像:

Select P.product_id
    , Coalesce( PT.name, P.name ) As Name
From product As P
    Left Join product_translations As PT
        On PT.product_id = P.product_id
            And PT.language_code = 'en-UK'

这确实意味着您提取产品信息的每个查询都需要左连接到翻译表,然后决定如果没有翻译值该怎么办:返回默认语言术语(如我在上面的示例中所示) ) 或返回 null。

I would go with a third alternative which is a hybrid of your existing design and solution #2. The columns that exist in your table now represent your "neutral" or default language. You would then add a table for each enttity that need translated values which would contain the PK of the main table, a key for the language code and a column for each value in the parent table that needed a translation.So we might have

Create Table product_translations
    (
    product_id int not null References product( id )
    , language_code varchar(5) not null
    , name ...
    , description ...
    , Primary Key ( product_id, language_code )
    ...
    )

Your queries would then look like:

Select P.product_id
    , Coalesce( PT.name, P.name ) As Name
From product As P
    Left Join product_translations As PT
        On PT.product_id = P.product_id
            And PT.language_code = 'en-UK'

It does mean every query where you pull product information will need a Left Join to the translations table and then decide what to do if there is no translation value: return the default language term (as I have in my example above) or return null.

回眸一笑 2024-11-06 13:24:36

我会使用(2)的稍微修改版本。我认为不要从产品表中删除 namedescription 列 - 在这种情况下,如果本地化版本不存在,您将始终拥有产品的默认值。

I would use a little modified version of (2). I think it's ok not to remove your name and description columns from product table - in this case you will always have default values for product if a localized version does not exist.

云胡 2024-11-06 13:24:36

我认为选项 #2 以错误的方向创建了 1:M 关系。现在您需要一个用于任何需要转换的基表的转换表。

我最近使用的解决方案应用于您的示例:

language
--------------
language_id
language_name

language_key
-------------
language_key_id
lang_key_name (or description)

translation
-------------------
translation_id
language_id
language_key_id
translation_text

product
--------------
product_id
product_name_key_id
product_description_key_id

您可能还想向密钥表添加“默认翻译”之类的内容,以便添加翻译是可选的,并且具有后备值。

最后,考虑在您的应用程序中缓存这些数据,因为它不太可能经常更改。

I think option #2 creates the 1:M relationship in the wrong direction. Now you need a translation table for any base table that requires translation.

A recent solution I used, applied to your sample:

language
--------------
language_id
language_name

language_key
-------------
language_key_id
lang_key_name (or description)

translation
-------------------
translation_id
language_id
language_key_id
translation_text

product
--------------
product_id
product_name_key_id
product_description_key_id

You also may want to add something like "default translation" to the key table, so that adding a translation is optional, and has a fallback value.

Finally, consider caching this data in your app, since it is not likely to change often.

迷路的信 2024-11-06 13:24:36

您确定所有内容至少都是英文的吗?翻译数量很少吗?如果是这样,我会说保持 product 不变,并为每个翻译添加一个类似的表:

TABLE: product_fi
=================================================================
| product_id | name           | description                     |
=================================================================
| 1          | Vimpain 1      | Tosi kiva vimpain. Osta heti!   |
-----------------------------------------------------------------

然后您可以 OUTER JOINCOALESCE 来当存在特定语言版本时获取它们,但依赖于英语版本:

SELECT
  coalesce(fi.name, en.name) AS name,
  coalesce(fi.description, en.description) AS description
FROM product en
LEFT OUTER JOIN product_fi fi ON en.product_id = fi.product_id
WHERE en.product_id = 1

Are you certain to always have all content at least in English? Is the number of translations quite small? If so, I'd say keep product as is, and add a similar table for each translation:

TABLE: product_fi
=================================================================
| product_id | name           | description                     |
=================================================================
| 1          | Vimpain 1      | Tosi kiva vimpain. Osta heti!   |
-----------------------------------------------------------------

Then you can OUTER JOIN and COALESCE to get specific language versions when they exist but fall back on English ones:

SELECT
  coalesce(fi.name, en.name) AS name,
  coalesce(fi.description, en.description) AS description
FROM product en
LEFT OUTER JOIN product_fi fi ON en.product_id = fi.product_id
WHERE en.product_id = 1
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文