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" 翻译存储空字符串,而不是根本不为他们存储记录。
为了避免这一切,您当然可以为所有内容添加翻译,即使它们在不同语言中是相同的。
我在我的应用程序中使用 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" 翻译存储空字符串,而不是根本不为他们存储记录。
为了避免这一切,您当然可以为所有内容添加翻译,即使它们在不同语言中是相同的。