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

CakePHP 3: order of translated data with missing translation strings

我在我的应用程序中使用 TranslationBehavior 来处理翻译后的数据。检索数据时,CakePHP returns 翻译后的字符串,或者如果此字符串不可用,则为默认语言环境的值。要请求数据,使用以下查询:

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

你可能会问,为什么要混合语言环境?在我的例子中,没有必要翻译所有的字符串,因为有些项目在两种语言中是相同的。

看看 CakePHP 如何查询翻译后的字段,然后在 PHP 级别合并它们,这是预期的行为,您确实必须在中使用条件表达式ORDER 子句。

我建议使用 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

并且如评论中所述,如果您选择“不翻译相同的字符串”路线,那么您应该避免为此类 "missing" 翻译存储空字符串,而不是根本不为他们存储记录。

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