我正在开发一个多语言软件。就应用程序代码而言,本地化不是问题。我们可以使用特定于语言的资源,并拥有各种与之配合良好的工具。
但是,定义多语言数据库模式的最佳方法是什么?假设我们有很多表(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)
)
每种解决方案都有优点和缺点,我想知道您使用这些方法的经验,您有什么建议,以及您将如何设计多语言数据库模式。
我正在寻找一些本地化的技巧,并找到了这个主题。
我想知道为什么要用这个:
CREATE TABLE T_TRANSLATION (
TRANSLATION_ID
)
所以你会得到user39603所建议的:
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'
你能不能把Translation表去掉,这样你就得到了这个:
table Product
productid INT PK, price DECIMAL
table ProductItem
productitemid INT PK, productid INT FK, text VARCHAR, languagecode CHAR(2)
view ProductView
select * from Product
inner join ProductItem
where languagecode='en'
我正在寻找一些本地化的技巧,并找到了这个主题。
我想知道为什么要用这个:
CREATE TABLE T_TRANSLATION (
TRANSLATION_ID
)
所以你会得到user39603所建议的:
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'
你能不能把Translation表去掉,这样你就得到了这个:
table Product
productid INT PK, price DECIMAL
table ProductItem
productitemid INT PK, productid INT FK, text VARCHAR, languagecode CHAR(2)
view ProductView
select * from Product
inner join ProductItem
where languagecode='en'
您需要记住,在创建多语言数据库时,您正在从产品表中删除名称或描述等字段,并将其移动到已翻译的资源中。
翻译后的资源可以是另一个表,就像我的例子一样,它被设计成与SQL视图一起工作,以简化查询和友好地开发底层应用程序
我分离了LabelTranslations,因为这是一个网页上字段标签的全局翻译表。你可以随意称呼它,它们是无状态的,不依赖于特定的产品或类别。
ProductTranslations的CategoryTranslations是有状态的,这意味着“name”的描述符将是实际的产品名称。
与简单的SQL视图相比,使用物化视图可以获得更好的性能(使用存储空间的成本和更多的精力用于底层应用程序开发来刷新它们),或者如果你想要使用更重的SQL视图。
在Postgres中创建类别物化视图:
CREATE MATERIALIZED VIEW VCategories AS (
SELECT cat.id, lng.iso_639_1_code, ct.descriptor, ct.value
FROM Categories cat
JOIN CategoryTranslations ct ON ct.category_id = cat.id
JOIN Languages lng ON lng.id = ct.language_id
);
查询ID为120的类别的所有翻译
SELECT * FROM VCategories WHERE id = 120 AND iso_639_1_code = 'en'
我觉得在使用应用程序的代码时很方便,您可以编写非常简单的代码来查询翻译和搜索记录