Php MySQL数据库I18N,一种JSON方法?

Php MySQL数据库I18N,一种JSON方法?,php,mysql,json,localization,internationalization,Php,Mysql,Json,Localization,Internationalization,更新:我在几年后遇到了这个问题:现在我知道这是一个非常糟糕的方法。请不要用这个。您可以始终为i18n使用附加表(例如products和products\u lang),为每个区域设置单独的条目:更好地用于索引,更好地用于搜索,等等 我正在尝试在MySQL/PHP站点中实现i18n 我读过一些回答说“i18n通常不是数据库的一部分”,我认为这有点狭隘。 那么产品名称呢,或者像在我的例子中一样,一个菜单结构和存储在数据库中的内容呢 考虑到语言应该是可扩展的,我想知道您对我的方法的看法,所以我试图避

更新:我在几年后遇到了这个问题:现在我知道这是一个非常糟糕的方法。请不要用这个。您可以始终为i18n使用附加表(例如
products
products\u lang
),为每个区域设置单独的条目:更好地用于索引,更好地用于搜索,等等


我正在尝试在MySQL/PHP站点中实现i18n

我读过一些回答说“i18n通常不是数据库的一部分”,我认为这有点狭隘。 那么产品名称呢,或者像在我的例子中一样,一个菜单结构和存储在数据库中的内容呢

考虑到语言应该是可扩展的,我想知道您对我的方法的看法,所以我试图避免“每种语言解决方案一列”


一种解决方案是为要翻译的字符串使用一个引用(id),并为每个可翻译列提供一个包含主键、字符串id、语言id和翻译的表

我认为另一个解决方案是使用JSON。因此,my db中的菜单项如下所示:

idmenu label
------ -------------------------------------------
5      {"en":"Homepage", "it":"pagina principale"}

您对这种方法有何看法?

首先想到的是:这显然会阻止在sql中进行精确搜索,其中label='Homepage'
第二:用户在搜索时可以看到不需要的结果(例如,当他的查询是在其他语言字符串中找到的)

这不是一个扩展。您失去了使用关系数据库的所有优势。通过与您类似的方式,您可以使用
serialize()
,以获得更好的解码性能,并将数据存储在文件中。在这种结构中使用SQL并没有什么特别的需要

我认为在所有语言中使用列是没有问题的。这在CMS的编程中更加容易。关系数据库不仅仅用于存储数据。它用于合理处理数据(例如,使用强大的内置机制)并控制数据的结构和完整性。

“一种解决方案是对要翻译的字符串使用引用(id),并且对于每个可翻译的列,都有一个带有主键、字符串id、语言id和翻译的表。”

我实现了一次,我所做的是使用现有的数据库模式,查找所有具有可翻译文本列的表,并为每个这样的表创建一个单独的表,仅包含这些文本列,以及一个附加的语言id和id,以将其绑定到原始表中的“数据”行。如果我有:

create table product (
  id          int          not null primary key
, sku         varchar(12)  not null
, price       decimal(8,2) not null
, name        varchar(64)  not null
, description text          
)
我将创建:

create table product_text (
  product_id  int          not null
, language_id int          not null
, name        varchar(64)  not null
, description text
, primary key (product_id, language_id)
, foreign key (product_id) references product(id)
, foreign key (language_id) references language(id)
)
我想这样问:

SELECT    product.id
,         COALESCE(product_text.name, product.name) name
,         COALESCE(product_text.description, product.description) description
FROM      product
LEFT JOIN product_text
ON        product.id = product_text.product_id 
AND       10         = product_text.language_id
(10正好是您现在感兴趣的语言id。)

正如您所看到的,原始表保留了文本列-如果当前语言没有可用的翻译,这些列将作为默认列

因此,无需为每个文本列创建单独的表,只需为所有文本列创建一个表(每个原始表)


正如其他人指出的那样,JSON的想法存在一个问题,即查询它几乎不可能,这反过来意味着无法在特定时间仅提取您需要的翻译。

我建议在数据库中保留一种主要语言,并使用额外的子系统来维护翻译。这是Drupal等web应用程序的标准方法。在您的软件/应用程序域中,很可能每个主要语言字符串都有一个翻译,因此您不必担心上下文或歧义。(事实上,为了获得最佳的用户体验,您应该努力为独特的功能提供独特的标签)

如果您想滚动您自己的桌子,您可以使用类似于:

create table translations (
  id          int          not null primary key
, source      varchar(255) not null // the text in the primary language
, lang        varchar(5)   not null // the language of the translation
, translation varchar(255) not null // the text of the translation
) 

您可能需要2个以上的字符作为语言,因为您可能需要en_US、en_UK等。

您的总体观点是正确的,但我的网站不需要基于文本的搜索。如果可能的话,所有其他的翻译都是用依赖于语言的模板来实现的。罗兰,对我来说,它看起来像是相同的鸡蛋,但只是在外形上:)我的意思是,这种方式很好,但与语言列相比没有特别的优势:接口编程更困难,表多2倍,键多。你能解释一下为什么要避免专栏吗?@Alexander所说的“语言专栏”是指为每种语言添加一个新的专栏吗?该解决方案在每次添加语言时都需要一个alter表。这可能会成为大型表的问题。此外,如果您想高效地搜索每一个语言列,您将拥有相当宽的表和大量的索引。对这些不同的方法进行基准测试是很有趣的,我假设您的解决方案对于中等规模的表的性能较差。关于“更难的接口”,我要么不理解你的意思,要么我不同意。请解释。我的意思是,通常使用多语言数据时,我们需要通过CMS进行操作。如果需要为一个实体创建接口,这比两个表和连接更容易。不仅在编程方面,而且在接口设计方面。为大型表添加列-操作缓慢,但只执行一次。当然,如果一个人需要不可预测的语言数量,并且每个人都有不同的用法,那么您的方法是唯一可能的。但这种情况并不常见(感谢上帝):)不过我完全理解你的想法,谢谢。@AlexanderPalamarchuk,谢谢你的回复。关于“如果你需要为一个实体创建一个接口——这比两个表和连接更容易。不仅在编程方面,而且在接口设计方面。”我不认为这会对接口产生什么影响。在我看来,接口应该是完全相同的——我认为从应用程序的角度来看,这是一个经典的例子,相同的接口,多个实现。问题是每次我必须添加语言时,我都必须更改模式。序列化并使用文件而不是SQL的概念是我想到的,但我不确定