CakePHP 3:翻译数据的顺序,缺少翻译字符串

时间:2018-04-26 09:49:01

标签: cakephp cakephp-3.x

我使用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已经提供了一个更简单的解决方案?

您可能会问,我们为什么要混合使用区域设置?就我而言,没有必要翻译所有字符串,因为有些项目在两种语言中都是相同的。

1 个答案:

答案 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

正如评论中所提到的,如果你去" 不翻译相同的字符串"路线,然后你应该避免为这样的"缺少"存储空字符串。翻译,而不是为他们存储记录。

为了避免这一切,您当然可以为所有内容添加翻译,即使它们在不同语言中是相同的。