多语言 MySQL 内容:如果指定的语言不可用,如何选择给定的语言或另一种语言?
我正在开发一个多语言网站 PHP,并且希望获取给定语言的内容(如果可用)和另一种语言的内容(如果不可用)。我将在下面尝试解释我的问题。如果有不清楚的地方,请告诉我。
我的表格:
内容
:content_id
、url
、日期
content_l10n
:content_id
、l10n_id
、标题
、说明
l10n
:l10n_id
、name
,order
第一种情况:
- 我的访客说法语。
- 我想要显示的内容有英语和法语两种版本。
- 该网站应显示法语内容。
→ 易于使用 JOIN
实现。
第二种情况:
- 我的访客说法语。
- 我想要显示的内容仅提供英文。
- 网站应显示英文内容。
→ 如何实现?是否可以在单个请求中实现?
一些注意事项:
- 这必须可以扩展到两种以上的语言。
- 该解决方案必须适用于这两种情况,因为我不知道在执行请求之前内容是否以正确的语言提供。
- 速度越快越好。
- 如果需要,可以更改表格。
- 我想选择多个
content
行(例如,对于标题列表)。 - 有时,
title
已翻译,但description
为NULL
。理想情况下,请求会选择给定语言的标题,但会回退到另一种语言进行描述。 - 最好设置后备的顺序(首先:给定语言,然后:按
order
ASC 排序的l10n
中的语言)。
我们将非常感谢您的帮助!先感谢您 !
亲切的问候,
奥利维尔
I'm developing a multilingual website PHP and would like to get content in a given language if available and in another one if not. I will try to explain my problem below. If something is not clear, please let me know.
My tables :
content
:content_id
,url
,date
content_l10n
:content_id
,l10n_id
,title
,description
l10n
:l10n_id
,name
,order
First case :
- My visitor speaks French.
- The content I want to display is available in both English and French.
- The website should display the French content.
→ Easy to implement with a JOIN
.
Second case :
- My visitor speaks French.
- The content I want to display is only available in English.
- The website should display the English content.
→ How to implement that ? Is it possible in a single request ?
Some notes :
- This has to be extensible to more than two languages.
- The solution has to work with either cases, as I don't know if the content is available in the right language before doing the request.
- The faster it is, the better it is.
- The tables can be changed if needed.
- I would like to select multiple
content
rows (for a list of titles, by example). - Sometimes,
title
is translated butdescription
isNULL
. Ideally, the request would select the title in the given language but would fallback to another language for the description. - It would be great to set the order of fallback (first : given language, then : languages from
l10n
ordered byorder
ASC).
Your help will be really appreciated ! Thank you in advance !
Kind regards,
olivier
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
此解决方案适用于许多行,但每种语言需要 1 个 LEFT JOIN,并且 JOIn 的顺序指定优先级。
(注意:我假设 $1 和 $2 是用户的前 2 种首选语言,并且它们缓存在会话中,因此不需要使用 l10n 进行额外的 JOIN)。
对于您的表结构,这是设置语言顺序的唯一有意义的方法。您需要一个额外的表来指定每个用户的语言首选项,而不是将订单存储在 l10n 表中。因此,假设您有一个表
,并且假设表 l10n 保留其“order”字段作为默认值。
如果这样做:
您将获得所有匹配的文档,以及用户指定的(或默认的)排序,因此应用程序可以轻松地解决这个问题。
现在的想法是避免从数据库中检索被用户喜欢的语言的现有翻译“遮蔽”的语言的所有行。
执行此操作的自然方法是 GROUP BY,但是 MySQL 没有可以在这里工作的聚合函数...
您可以执行依赖子查询(用于标题和描述);抓取一行还可以,但如果你想抓取多行,速度就非常慢。
但你也可以做点别的事!这依赖于 MySQL 的非标准 GROUP BY 子句的一些可疑行为...
首先,收集要显示的“content_id”列表(分页搜索查询的结果,等等)。然后你就可以做类似下面恐怖的事情:
This solution works for many rows but you need 1 LEFT JOIN per language, and the order of the JOIns specifies priority.
(Note : I suppose here that $1 and $2 are the user's first 2 preferred languages, and they are cached in the session, so there is no need for extra JOINs with l10n).
With your table structure this is the only meaningful way to set the language order. You would need an extra table to specify each user's language preferences instead of storing the order in l10n table. So let's suppose you have a table
And let's suppose the table l10n keeps its "order" field, as a default.
If you do this :
You'll get all the documents that match, and also the user-specified (or default) ordering, so the application can easily sort this out.
Now the idea is to avoid retrieving from the database all the rows that are in languages that are "shadowed" by an existing translation in a language that the user prefers.
The natural way to do this is a GROUP BY, but MySQL doesn't have an aggregate function that would work here...
You could do a dependent subquery (for title and description) ; this would be OK to grab one row, but horribly slow if you want to grab many rows.
But you can also do something else ! That relies on some shady behaviour of MySQL's non-standard GROUP BY clause...
First, gather a list of "content_id"'s that you want to display (result of a paginated search query, whatever). Then you can could do something like the horror that follows :
这应该为您提供第二种情况的基础:
关于性能,您需要在
content.content_id
、content_l10n.content_id
、l10n.l10n_id
中建立索引> 和l10n.order
。this should give you the basis for the second case:
About performance, you need an index in
content.content_id
,content_l10n.content_id
,l10n.l10n_id
andl10n.order
.