【问题标题】:Database Design - Multilingual Website数据库设计 - 多语言网站
【发布时间】:2012-11-19 18:31:52
【问题描述】:

我有一个多语言网站,它的用户可以拥有不同语言的个人资料,例如,每个用户的个人资料都可以用“英语”、“法语”和“西班牙语”发布,例如 LinkedIn。

现在,我是一个使用“英语”语言查看网站的用户,因此当我转到其他会员个人资料页面时,我应该看到该会员个人资料以“英语”显示,如果该个人资料不可用的话语言,我应该在该成员“main_lang”中看到该配置文件。

所以我有一个“成员”表,其中有一列是“published_profile_langs”,在这个列中,每个成员发布他的个人资料的语言将以逗号分隔:“english,spanish”和“main_lang” col 是用户的主要语言(他的个人资料肯定会在 main_lang 中发布,因为我们正在询问有关注册步骤的详细信息)。

另一方面,成员详细信息存储在不同的表中,例如“members_details_english”、“members_details_spanish”、“members_details_french”。

我想加入我的查询,但我管理的方式似乎不可能,目前我需要使用 2 个查询来加载上述场景中的成员详细信息,我在“members_profile.php”中的代码是:

// FIRST QUERY
$check_member = mysql_query("SELECT main_lang, profile_published_langs FROM members WHERE id = '$this_user_id'");
    while($row = mysql_fetch_array($check_member)){
            $this_main_lang = $row['main_lang'];
            $this_profile_published_langs = $row['profile_published_langs'];
        }
    $this_profile_published_langs_arr = explode(',', $this_profile_published_langs);
    if(!in_array($lang, $this_profile_published_langs_arr)) $lang = $this_main_lang;

$details_table = 'members_details_' . $lang;

// SECOND QUERY
$get_details = mysql_query("SELECT * FROM $details_table WHERE member_id = '$this_user_id'");
        while($row_details = mysql_fetch_array($get_details)){
            //blah blah
        }

有没有更好的方法来实现这一点?也许以某种方式查询一次而不是两次?这种情况下有更好的数据库结构吗?

我将不胜感激任何形式的帮助

【问题讨论】:

  • 您的问题被标记为 MySQL 但包含 PHP 代码 :-?

标签: mysql database-design


【解决方案1】:

尝试将语言视为数据库中的另一个实体。使用表members 存储所有不依赖于语言的数据,并有第二个表包含数据; members_i18n - memebers_internationalization 的缩写。

在第一个表中,您可以有一个名为main_language_id 的列,并使用第二个表来存储每个成员的不同语言的数据列,方法是通过member_idlanguage_id 与它相关联。通过这种方式,您可以获取所有语言的每个成员的数据,仅获取他们的主要语言或您需要的任何特定语言集。

另外,您无需在表中使用序列化数据,例如 profile_published_langs

所以一些示例查询是:

-- Main language
SELECT * 
FROM member AS m
JOIN member_i18n AS mi
  ON m.member_id = mi.member_id
  AND m.main_language_id = mi.language_id

-- Specific language
SELECT * 
FROM member AS m
JOIN member_i18n AS mi
  ON m.member_id = mi.member_id
WHERE mi.language_id = 'eng'

-- All languages
SELECT * 
FROM member AS m
JOIN member_i18n AS mi
  ON m.member_id = mi.member_id

编辑:

就我个人而言,我通常使用如下语言的第三张表:

CREATE TABLE `language` (
  `language_id` char(3) NOT NULL,
  `name` varchar(30) NOT NULL,
  `code2` char(2) NOT NULL,
  PRIMARY KEY (`language_id`)
);
-- Sample data
INSERT INTO `language` (`language_id`, `name`, `code2`) VALUES
  ('deu', 'Deutsch', 'de'),
  ('eng', 'English', 'en');

我发现它在打印多语言数据时非常有用。

编辑 2:

因此,要以“当前”语言及其主要语言为用户获取数据,只需编写一个 single 查询,如下所示:

-- Current language (i.e. 'eng') + member's main language
SELECT * 
FROM member AS m
JOIN member_i18n AS mi
  ON m.member_id = mi.member_id
WHERE mi.language_id = m.main_language_id
  OR mi.language_id = 'eng'

您最终会得到一两行,具体取决于会员的个人资料。

【讨论】:

  • 这仍然无法解决 1 次查询的问题,谢谢
  • 使用我在此处编写的解决方案,您可以获取成员的详细信息,只需使用其主要语言和“当前”语言(如果存在)的单个查询。我已经更新了我的答案。结果你只会得到一两行。
【解决方案2】:

您可以拥有一个表成员(id_user、mainlang、firstname...)和一个表配置文件(id_user、语言和该语言的所有数据)。对于用户,每种语言都有一行。你的选择是这样的

select * from profile where id_user = $userId and language = $lang

【讨论】:

    【解决方案3】:

    我可能会构建一个用户表、一个语言表和一个映射表

    1. user_main - 所有常用列,此处有邮件语言列
    2. 语言表 - 无论你想保留什么,代码等,加上一列 - lang 表名(相当于你的 user_details_spanish 等表)
    3. 映射表-用户ID,语言ID(这里的一行表示 特定用户拥有该语言的个人资料)

    现在,我同意,您可能仍需要两个查询,但我认为它更易于管理,因为表名可从 lang 表中获得,并且您可以将其保留在会话中(例如,您让用户选择的位置从要切换到哪种语言的下拉菜单中,表名本身就可以在那里使用,因此您不必获取它)...

    如果这个思路有帮助,请告诉我。也许我可以提供更多帮助...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-30
      • 1970-01-01
      • 2023-03-26
      相关资源
      最近更新 更多