我使用TranslationBehavior来处理我的应用中的翻译数据。检索数据时,CakePHP返回已翻译的字符串,或者如果此字符串不可用,则返回默认语言环境的值。要请求数据,请使用以下查询:
$items = $this->Model->find('all')
->all()
->extract('name');
要对输出进行排序,查询为:
$items = $this->Model->find('all')
->order([$this->Model->translationField('name') => 'ASC'])
->all()
->extract('name');
这适用于所有默认语言环境项目和所有已翻译项目。但是当缺少记录的翻译时,它将破坏顺序。在这种情况下,将返回正确的回退值,但订单不再正确。输出如下:
['A... (Translated)', 'B... (Translated)', 'A... (Default)', 'C... (Default)']
我期望的是以下顺序:
['A... (Default)', 'A... (Translated)', 'B... (Translated)', 'C... (Default)']
为实现这一目标,我将查询更改为:
$items = $this->Model->find('all')
->order(['IF('.$this->Model->translationField('name').' != "", '.$this->Model->translationField('name').', Model.name)' => 'ASC'])
->all()
->extract('name');
这给出了预期的顺序:
['A... (Default)', 'A... (Translated)', 'B... (Translated)', 'C... (Default)']
问题是:这是处理混合语言环境顺序的正确方法吗?或者我错过了什么,CakePHP已经提供了一个更简单的解决方案?
您可能会问,我们为什么要混合使用区域设置?就我而言,没有必要翻译所有字符串,因为有些项目在两种语言中都是相同的。
答案 0 :(得分:1)
查看CakePHP如何查询已翻译的字段,并在以后的PHP级别合并它们,这是预期的行为,您确实必须在ORDER
子句中使用条件表达式。 / p>
我建议使用CASE
表达式,因为IF()
函数是MySQL特定的,如:
$query = $this->Model->find();
$query
->orderAsc(
$query->newExpr()->addCase(
[
$query->newExpr()->isNotNull($this->Model->translationField('name'))
],
[
$query->identifier($this->Model->translationField('name')),
$query->identifier('Model.name')
]
)
)
// ...
这将生成类似于:
的表达式ORDER BY
CASE WHEN Model_name_translation.content IS NOT NULL
THEN Model_name_translation.content
ELSE Model.name END
ASC
正如评论中所提到的,如果你去" 不翻译相同的字符串"路线,然后你应该避免为这样的"缺少"存储空字符串。翻译,而不是为他们存储记录。
为了避免这一切,您当然可以为所有内容添加翻译,即使它们在不同语言中是相同的。