草庐IT

php - 多语言 MySQL 内容 : how to select a given language or another if the one specified isn't available?

coder 2023-10-18 原文

我正在开发一个 PHP 多语言网站,如果可用,我想获取给定语言的内容,如果不可用,则希望获取另一种语言的内容。我将在下面尝试解释我的问题。如果有什么不清楚的地方,请告诉我。

我的表:

  • content : content_id, url, date
  • content_l10n : content_id, l10n_id, title, description
  • l10n : l10n_id, name, order

第一种情况:

  • 我的访客说法语。
  • 我要显示的内容有英文和法文两种版本。
  • 该网站应显示法语内容。

→ 使用 JOIN 很容易实现。

第二种情况:

  • 我的访客说法语。
  • 我要显示的内容只有英文版本
  • 网站应显示英文内容。

→ 如何实现?是否可以在单个请求中实现?

一些注意事项:

  • 这必须可以扩展到两种以上的语言。
  • 解决方案必须适用于任何一种情况,因为在发出请求之前我不知道内容是否以正确的语言提供。
  • 越快越好。
  • 可以根据需要更改表格。
  • 我想选择多个 content 行(例如,对于标题列表)。
  • 有时,title 已翻译,但descriptionNULL。理想情况下,请求会选择给定语言的标题,但会回退到另一种语言的描述。
  • 设置后备顺序会很棒(首先:给定语言,然后:来自 l10n 的语言,按 order ASC 排序)。

非常感谢您的帮助!提前谢谢你!

亲切的问候,

奥利维耶

最佳答案

此解决方案适用于许多行,但每种语言需要 1 个 LEFT JOIN,并且 JOIn 的顺序指定优先级。

SELECT   c.url, c.date, 
         COALESCE( c1.title, c2.title ),
         COALESCE( c1.description, c2.description )
FROM      content c
LEFT JOIN content_l10n c1 ON (c1.content_id = c.content_id AND c1.l10n_id=$1)
LEFT JOIN content_l10n c2 ON (c2.content_id = c.content_id AND c2.l10n_id=$2)

(注意:我在这里假设 $1 和 $2 是用户的前 2 种首选语言,它们缓存在 session 中,因此不需要额外的 l10n JOIN)。

对于您的表结构,这是设置语言顺序的唯一有意义的方法。您将需要一个额外的表来指定每个用户的语言首选项,而不是将顺序存储在 l10n 表中。假设你有一张 table

user_l10n( user_id, l10n_id, order )

让我们假设表 l10n 保留其“order”字段作为默认值。

如果你这样做:

SELECT   ..., COALESCE(ul.order,l.order) AS order
FROM      
          content      c
JOIN      content_l10n cl USING (content_id)
JOIN      l10n         l  USING (l10n_id)                -- get default language order
LEFT JOIN user_l10n    ul ON    (ul.l10n_id=l.l10n_id    -- get user preferences if available
                                 AND ul.user_id=$user_id)
WHERE search condition on content, etc
ORDER BY content_id, COALESCE(ul.order,l.order)

您将获得所有匹配的文档,以及用户指定的(或默认的)排序,因此应用程序可以轻松地对此进行排序。

现在的想法是避免从数据库中检索所有行,这些行的语言被用户喜欢的语言的现有翻译“遮蔽”。

执行此操作的自然方法是 GROUP BY,但 MySQL 没有适用于此处的聚合函数...

你可以做一个依赖子查询(用于标题和描述);抓取一行没问题,但如果您想抓取多行,速度会非常慢。

但是你也可以做点别的!这依赖于 MySQL 的非标准 GROUP BY 子句的一些可疑行为......

首先,收集您要显示的“content_id”列表(分页搜索查询的结果,无论如何)。然后你可以做类似下面恐怖的事情:

SELECT * FROM
(
    SELECT content_id, title FROM 
    (
        SELECT    c.content_id, c.title
        FROM      
                  content      c
        JOIN      content_l10n cl USING (content_id)
        JOIN      l10n         l  USING (l10n_id)
        LEFT JOIN user_l10n    ul ON    (ul.l10n_id=l.l10n_id AND ul.user_id=$user_id)
        WHERE cl.content_id IN ($list) AND c.title IS NOT NULL
        ORDER BY content_id, COALESCE(ul.order,l.order)
    ) d GROUP BY content_id
) t
JOIN
(
    SELECT content_id, description FROM 
    (
        SELECT    c.content_id, c.description
        FROM      
                  content      c
        JOIN      content_l10n cl USING (content_id)
        JOIN      l10n         l  USING (l10n_id)
        LEFT JOIN user_l10n    ul ON    (ul.l10n_id=l.l10n_id AND ul.user_id=$user_id)
        WHERE cl.content_id IN ($list) AND c.description IS NOT NULL
        ORDER BY content_id, COALESCE(ul.order,l.order)
    ) d GROUP BY content_id
)
USING (content_id)

关于php - 多语言 MySQL 内容 : how to select a given language or another if the one specified isn't available?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5919733/

有关php - 多语言 MySQL 内容 : how to select a given language or another if the one specified isn't available?的更多相关文章

随机推荐