【问题标题】:Suggestion for database structure for multilanguage多语言数据库结构建议
【发布时间】:2011-06-12 03:08:10
【问题描述】:

使用 PHP 5.x 和 MySQL 5.x

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

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

【问题讨论】:

    标签: php database-design


    【解决方案1】:

    实际上没有必要拥有多张桌子,除非您计划拥有数百万个故事......我通常会使用两张桌子;一个用于item,另一个用于localized item

    例如,一个故事会是这样的

    表格“故事”

    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..
    

    执行查询只需JOINing 两个表即可:

    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}
    

    【讨论】:

      【解决方案2】:

      最好的方法是将故事存储为多值属性。正如@Yanick 向您展示的那样。 如果您仅使用该故事可用的语言填充您的语言选择元素,则界面效果会更好。

      【讨论】:

        【解决方案3】:

        当文本不是很长时,另一种不错的方法是:星期名称、蒙特...在我的应用程序中,我正在本地化音乐流派和乐器。使用文本字段存储 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
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-04-21
          • 2013-03-22
          • 2023-03-26
          • 2012-01-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多