数据库设计:如何支持多语言网站?
假设我有这样的表格:
TABLE: product
=================================================================
| product_id | name | description |
=================================================================
| 1 | Widget 1 | Really nice widget. Buy it now! |
-----------------------------------------------------------------
如果我想提供多语言支持,最好的方法是什么?
可能的解决方案:
- 在上表中添加“语言”列;这将指示特定记录的语言。 (我不认为这对我来说是一个选择,因为其他表将使用product.product_id作为其FK。)
- 删除product表中的任何可翻译列(在上面的示例中,product.name和product.description)并将其放入在带有“语言”列的单独表中。该新表将使用product.product_id 作为 FK。 (我不会在应用程序的第一个版本中支持多语言。此解决方案意味着我必须执行额外的 JOIN 才能获取最初支持的语言的值。)
- 还有什么我没有考虑的吗?
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:
- 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.)
- 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.)
- Something else that I didn't consider?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我会选择解决方案 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.我会选择第三种替代方案,它是您现有设计和解决方案#2 的混合体。表中存在的列现在代表您的“中性”或默认语言。然后,您将为需要翻译值的每个实体添加一个表,其中包含主表的 PK、语言代码的键以及父表中需要翻译的每个值的列。因此,我们可能有
您的查询然后看起来像:
这确实意味着您提取产品信息的每个查询都需要左连接到翻译表,然后决定如果没有翻译值该怎么办:返回默认语言术语(如我在上面的示例中所示) ) 或返回 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
Your queries would then look like:
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.
我会使用(2)的稍微修改版本。我认为不要从产品表中删除
name
和description
列 - 在这种情况下,如果本地化版本不存在,您将始终拥有产品的默认值。I would use a little modified version of (2). I think it's ok not to remove your
name
anddescription
columns from product table - in this case you will always have default values for product if a localized version does not exist.我认为选项 #2 以错误的方向创建了 1:M 关系。现在您需要一个用于任何需要转换的基表的转换表。
我最近使用的解决方案应用于您的示例:
您可能还想向密钥表添加“默认翻译”之类的内容,以便添加翻译是可选的,并且具有后备值。
最后,考虑在您的应用程序中缓存这些数据,因为它不太可能经常更改。
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:
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.
您确定所有内容至少都是英文的吗?翻译数量很少吗?如果是这样,我会说保持
product
不变,并为每个翻译添加一个类似的表:然后您可以
OUTER JOIN
和COALESCE
来当存在特定语言版本时获取它们,但依赖于英语版本: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:Then you can
OUTER JOIN
andCOALESCE
to get specific language versions when they exist but fall back on English ones: