我正在开发一个多语言软件。就应用程序代码而言,本地化不是问题。我们可以使用特定于语言的资源,并拥有各种与之配合良好的工具。

但是,定义多语言数据库模式的最佳方法是什么?假设我们有很多表(100个或更多),每个表可以有多个可以本地化的列(大多数nvarchar列应该是可本地化的)。例如,其中一个表可能保存产品信息:

CREATE TABLE T_PRODUCT (
  NAME        NVARCHAR(50),
  DESCRIPTION NTEXT,
  PRICE       NUMBER(18, 2)
)

我可以想到三种方法来支持NAME和DESCRIPTION列中的多语言文本:

Separate column for each language When we add a new language to the system, we must create additional columns to store the translated text, like this: CREATE TABLE T_PRODUCT ( NAME_EN NVARCHAR(50), NAME_DE NVARCHAR(50), NAME_SP NVARCHAR(50), DESCRIPTION_EN NTEXT, DESCRIPTION_DE NTEXT, DESCRIPTION_SP NTEXT, PRICE NUMBER(18,2) ) Translation table with columns for each language Instead of storing translated text, only a foreign key to the translations table is stored. The translations table contains a column for each language. CREATE TABLE T_PRODUCT ( NAME_FK int, DESCRIPTION_FK int, PRICE NUMBER(18, 2) ) CREATE TABLE T_TRANSLATION ( TRANSLATION_ID, TEXT_EN NTEXT, TEXT_DE NTEXT, TEXT_SP NTEXT ) Translation tables with rows for each language Instead of storing translated text, only a foreign key to the translations table is stored. The translations table contains only a key, and a separate table contains a row for each translation to a language. CREATE TABLE T_PRODUCT ( NAME_FK int, DESCRIPTION_FK int, PRICE NUMBER(18, 2) ) CREATE TABLE T_TRANSLATION ( TRANSLATION_ID ) CREATE TABLE T_TRANSLATION_ENTRY ( TRANSLATION_FK, LANGUAGE_FK, TRANSLATED_TEXT NTEXT ) CREATE TABLE T_TRANSLATION_LANGUAGE ( LANGUAGE_ID, LANGUAGE_CODE CHAR(2) )

每种解决方案都有优点和缺点,我想知道您使用这些方法的经验,您有什么建议,以及您将如何设计多语言数据库模式。


当前回答

我通常会选择这种方法(不是实际的sql),这对应于您的最后一个选项。

table Product
productid INT PK, price DECIMAL, translationid INT FK

table Translation
translationid INT PK

table TranslationItem
translationitemid INT PK, translationid INT FK, text VARCHAR, languagecode CHAR(2)

view ProductView
select * from Product
inner join Translation
inner join TranslationItem
where languagecode='en'

因为将所有可翻译文本放在一个地方可以使维护工作更加容易。有时翻译外包给翻译机构,这样你就可以给他们发送一个大的导出文件,然后很容易地导入回来。

其他回答

我通常会选择这种方法(不是实际的sql),这对应于您的最后一个选项。

table Product
productid INT PK, price DECIMAL, translationid INT FK

table Translation
translationid INT PK

table TranslationItem
translationitemid INT PK, translationid INT FK, text VARCHAR, languagecode CHAR(2)

view ProductView
select * from Product
inner join Translation
inner join TranslationItem
where languagecode='en'

因为将所有可翻译文本放在一个地方可以使维护工作更加容易。有时翻译外包给翻译机构,这样你就可以给他们发送一个大的导出文件,然后很容易地导入回来。

看看这个例子:

PRODUCTS (
    id   
    price
    created_at
)

LANGUAGES (
    id   
    title
)

TRANSLATIONS (
    id           (// id of translation, UNIQUE)
    language_id  (// id of desired language)
    table_name   (// any table, in this case PRODUCTS)
    item_id      (// id of item in PRODUCTS)
    field_name   (// fields to be translated)
    translation  (// translation text goes here)
)

我认为没有必要解释,结构本身就说明了这一点。

我同意随机发生器。我不明白你为什么需要一个表“翻译”。

我想,这就足够了:

TA_product: ProductID, ProductPrice
TA_Language: LanguageID, Language
TA_Productname: ProductnameID, ProductID, LanguageID, ProductName

对于每个可翻译表都有一个相关的翻译表,您怎么看?

CREATE TABLE T_PRODUCT (pr_id int, PRICE NUMBER(18, 2))

CREATE TABLE T_PRODUCT_tr (pr_id INT FK, languagecode varchar, pr_name text, pr_descr text)

通过这种方式,如果你有多个可翻译的列,它只需要一个连接就可以得到它+由于你没有自动生成translationid,它可能更容易将项目与其相关的翻译一起导入。

这样做的负面影响是,如果您有一个复杂的语言回退机制,您可能需要为每个翻译表实现该机制——如果您依赖于某个存储过程来实现该机制的话。如果你从应用程序中这样做,这可能不是一个问题。

让我知道你的想法-我也将为我们的下一个申请做出决定。 到目前为止我们使用的是你们的第三种。

下面的方法是否可行?假设您有多个表,其中有超过1个列需要转换。所以对于产品来说,你可能同时需要翻译产品名称和产品描述。你能做到以下几点吗?

CREATE TABLE translation_entry (
      translation_id        int,
      language_id           int,
      table_name            nvarchar(200),
      table_column_name     nvarchar(200),
      table_row_id          bigint,
      translated_text       ntext
    )

    CREATE TABLE translation_language (
      id int,
      language_code CHAR(2)
    )