【问题标题】:Database localization数据库本地化
【发布时间】:2010-11-22 07:31:41
【问题描述】:

我有许多包含需要本地化的namedescription 列的数据库表。我最初尝试设计一个支持这一点的数据库模式是这样的:

product
-------
id
name
description


local_product
-------
id
product_id
local_name
local_description
locale_id


locale
------
id
locale

但是,此解决方案需要为每个包含 name 的表和需要 localization 的说明列创建一个新的 local_ 表。为了避免这种开销,我重新设计了架构,以便只需要一个 localization

product
-------
id
localization_id


localization    
-------
id    
local_name
local_description
locale_id


locale
------
id
locale

以下是当有 2 个表(产品和国家/地区)需要本地化时存储在此架构中的数据示例:

国家

id,     localization_id
-----------------------
1,      5

产品

id,     localization_id
-----------------------
1,      2

本地化

id,     local_name,   local_description,     locale_id
------------------------------------------------------
2,      apple,        a delicious fruit,     2
2,      pomme,        un fruit délicieux,    3
2,      apfel,        ein köstliches Obst,   4
5,      ireland,      a small country,       2
5,      irlande,      un petite pay,         3

语言环境

id,     locale
--------------
2,      en
3,      fr
4,      de

注意localization表的复合主键是(id, locale_id),但product表中的外键只指这个复合PK的第一个元素。从规范化的 POV 来看,这似乎是“一件坏事”。

有什么办法可以解决这个问题,或者,是否有一个完全不同的架构支持本地化,而无需为每个可本地化的表创建单独的表?

更新: 许多受访者提出了一种解决方案,该解决方案需要为每个可本地化的表创建一个单独的表。然而,这正是我想要避免的。我上面提出的架构几乎可以让我满意地解决问题,但我对localization_id 外键仅引用localization 表中相应主键的一部分这一事实感到不满。

谢谢, 唐

【问题讨论】:

  • “但我对 localization_id 外键仅引用本地化表中相应主键的一部分这一事实感到不满”。我没看出问题,产品和本地化是一对多的关系,数据库结构符合要求,你找到了一个很好的解决方案。
  • 这应该发布在dba.stackexchange.com

标签: database-design internationalization schema


【解决方案1】:

我觉得还好。您正在描述产品与其本地化文本之间的一对多关系。

我想知道您是否也应该将英语本地化而不是在您的产品表中对其进行非规范化。

【讨论】:

  • 我已修改架构以纳入您的建议
  • 本地化的重点在于“事物”和名称之间存在一对多的关系。所以很自然地,“事物”表中的引用不能是本地化表的完整主键,因为这会将关系限制为一对一。建立多对一关系的更常见方法是将“一”端的标识符发布到“多”端,但在这里这样做会遇到问题,因为本地化表必须引用许多不同的表,造成混乱、松散定义的外键引用。
【解决方案2】:

我喜欢这个想法,但会朝另一个方向迈出一步,并为每一列翻译一个本地化条目:

国家

id,     localization_id
-----------------------
1,      5

产品

id,     name_locale_id,  description_locale_id
----------------------------------------------
1,      2,               8

本地化

id,     locale_id,    value
------------------------------------------------------
2,      2             apple
2,      3             pomme
2,      4             apfel
5,      2             ireland
5,      3             irlande
8,      2             a delicious fruit
8,      3             un fruit délicieux
8,      4             ein köstliches Obst
9,      2             a small country
9,      3             un petite pay

语言环境

id,     locale
--------------
2,      en
3,      fr
4,      de

本地化的PK是(id, locale_id)。 id 在其他几个表中也是 FK 引用,这没问题。如果你愿意,你可以添加一个代理 PK,只要你在 (id, locale_id) 上仍然有一个唯一的索引。

这样做的好处是它是一个单一的本地化表,它适用于架构中的任何表,无论它具有什么字段(您不限于同时拥有任何已本地化的名称和描述)。缺点是使用本地化表时可能会影响性能——尽管您可能只缓存给定 locale_id 的整个内容,因此当您查找条目时,您只需要查找给定的 id(因为您的缓存是已根据语言键入)。

您还可以考虑在产品表中保留默认名称和描述字段,以防当前语言缺少条目,或者在输入时用户未指定语言。如果您要移植现有应用程序,也会出现这种情况,那里已经有值(没有语言环境信息)。

【讨论】:

    【解决方案3】:

    我认为正确的方法是创建额外的表,然后执行额外的步骤并从第一个表中删除所有特定于语言的资源。

    所以你有:

    产品

    id 
    -name removed
    -description removed
    

    产品本地化

    productid, locale_id, name,   description
    ------------------------------------------------------
    1,         3,         pomme,  un fruit délicieux
    1,         4,         apfel,  ein köstliches Obst
    1,         1,         apple,  a delicious fruit
    

    语言环境

    id,     locale
    --------------
    1,      en
    3,      fr
    4,      de
    

    【讨论】:

    • 当有多个表包含可本地化的内容时,此架构将不起作用
    • 每个可本地化的内容都需要一个额外的表格。我不认为你能解决这个问题。一些可本地化的表可能没有名称或描述,您会看到,或者可能有更多需要翻译的字段。这当然打破了规范化的最佳实践。使用额外的表格。
    • 在这种情况下,可以安全地假设每个可本地化的表只需要名称和描述即可本地化
    【解决方案4】:

    如果我理解正确,您的问题只是因为您想在多个表中对名称和描述使用相同的语言本地化。在这种情况下,您无法在本地化表中添加 prod_id。您设计中的另一个问题是它不能优雅地处理同一产品的多种语言本地化。你可以调整它来工作:

    如果名称和描述是唯一需要本地化的字段,您可以执行以下操作。

    产品(ID、名称、描述、tanslation_row_id)

    Product_translations(ID、名称、描述、lang_id、translation_id)

    translation_row_id 将是指向 Product_translations.ID 的外键 然而,translation_id 将指向同一表中的父记录,该表将用作所有语言特定记录的公共记录。

    示例记录

    产品

    (ID, name, description, translation_row_id)
    (p1, apples,a red fruit, tr1)
    (p2, mango, a yellow fruit, tr2)
    

    产品翻译

    (ID, name, description, lang_id, translation_id)
    (tr1, apples, a red fruit, ENU, null)
    (tr2, mango, a yellow fruit, null)
    (tr3, pomme,un fruit rouge, FRA,tr1)
    (tr4, mangue,a yellow fruit, SPA,tr2)
    

    给定语言代码,您可以使用以下 SQL 查询提取名称和描述值

    select T.name, T.description
    from product_translations T 
    where T.translation_id = 
         (select T2.ID 
          from Product P,Product_translations T2 
          where P.translation_row_id = t2.ID
          ) 
         and T.lang_id = '&langID';
    

    重要提示:我假设产品表有更多不需要此转换的属性。 '&langID' 是 SQL 查询的一个参数,它会询问用户他选择的语言代码

    【讨论】:

    • 很棒的建议,我可能会尝试一下。但是,我可能会从 Product(和其他可本地化的)表中删除名称和描述,因为它似乎是多余的。此外,product_translations 表应该被称为更通用的东西,比如“翻译”,因为实际上它会包含本地化的国家/地区、产品等。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-12
    • 2012-04-19
    • 2020-05-03
    • 2012-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多