建议多语言的数据库结构

时间:2011-06-12 03:08:10

标签: php database-design

使用PHP 5.x和MySQL 5.x

所以我昨天问了一个关于处理多语言动态数据的最佳方法的问题,这个问题是数据库结构处理这个问题的好方法。我在数据库中有类似故事的条目。我的计划是为数据库中可用的每种语言存储不同版本的故事。因此,如果网站支持英语和西班牙语,那么在管理工具中,他们可以添加故事的英文版本和故事的西班牙语版本。

我的想法是在数据库中有一个单独的表,每种语言都有一个表。因此,英语版的一个故事表,一个用于西班牙语,一个用于其他任何语言。然后在前端我只是允许访问者选择查看网站的语言,并通过变量知道要查询的表格来获取该版本的故事。但有一个问题是,如果没有西班牙语版本,但他们选择西班牙语?这是一个很好的解决方案还是有更好的方法来做到这一点?寻找建议。

3 个答案:

答案 0 :(得分:3)

除非你计划拥有数百万个故事,否则确实没有必要使用多个表...我通常会选择两个表格;一个用于,另一个用于本地化项

例如,一个故事就像是

表"故事"

id INTEGER (Primary Key)
creation_date DATE_TIME
author VAR_CHAR(32)
..other general columns..

表" story_localized"

story_id INTEGER (Foreign Key of story.id) \
lang CHAR(2)                               -- (Indexed, unique -- story_id+lang)
content TEXT
..other localized columns..

执行查询只是JOIN两个表的问题:

SELECT s.*, sl.*
  FROM story s
  JOIN story_localized sl ON s.id = sl.story_id
 WHERE s.id = 1         -- the story you're looking for here
   AND sl.lang = 'en'   -- your language here
   -- other conditions here

这种配置有一些优点:

  • 您的所有数据都在同一个表中,无需同步CRUD操作
  • 您可以为任何故事添加新语言,而无需创建更多表格

** 编辑 **

作为奖励,这里有一个"技巧"无论语言被写入

,都能轻松地检索故事
SELECT *
  FROM (SELECT * 
          FROM story s
          JOIN story_localized sl ON s.id = sl.story_id
         WHERE s.id = {storyId}
           AND sl.lang = {desiredLanguage}    -- example : 'es'
        UNION
        SELECT * 
          FROM story s
          JOIN story_localized sl ON s.id = sl.story_id
         WHERE s.id = {storyId}
           AND sl.lang = {defaultLanguage}    -- example : 'en'
        UNION
        SELECT * 
          FROM story s
          JOIN story_localized sl ON s.id = sl.story_id
         WHERE s.id = {storyId}
         LIMIT 1                              -- ..get the first language found
) story_l
LIMIT 1              -- only get the first SELECTed row found

将尝试在{desiredLanguage}中抓取故事,如果该语言不可用,请尝试在{defaultLanguage}(即网站的默认语言)中找到该故事,如果还没有找到,那么获取故事的语言并不重要,那么,找到第一个找到的语言。所有在一个查询中,您只需要3个参数:故事ID,所需语言和默认后备语言。

此外,您可以通过简单的查询轻松找到故事的语言:

SELECT sl.lang
  FROM story_localized sl
 WHERE sl.story_id = {storyId}

答案 1 :(得分:1)

执行此操作的最佳方法是将故事存储为多值属性。正如@Yanick告诉你的那样。 如果只使用那些可用故事的语言填充语言选择元素,那么界面会更好。

答案 2 :(得分:0)

另一个很好的方法,当它不是一个长文本:周名称,monts ...在我的应用程序中我正在本地化音乐流派和乐器。使用文本字段存储json数据。

所以在我的音乐剧“流派”表中,有一个名为“lang”的文本字段。在我有以下json结构:

{"es_gl":"MARCHA ESPAÑOLA", "es_EN" : "SPANISH MARCH"}

然后使用PHP很容易从json结构中获取数据。假设我的$ genre变量有类型。

$myJSON = json_decode($genre->lang);
echo $myJSON->es_gl // This echoes MARCHA ESPAÑOLA
echo $myJSON->es_es // This echoes SPANISH MARCH

当您的本地化数据不大时,如帖子或博客,这是一个很好的解决方案。