如何在 CakePHP 中使翻译字段可滑动 3.x
How do you make a translation field sluggable in CakePHP 3.x
如果你曾经遇到过一个问题,当你不能在翻译的字段上发出一个 sluggable 行为时,我觉得是的。
每当您为实体保存翻译时,'slug' 属性 将被省略,因为在保存翻译实体时它不是脏的。
- 您保存了一个实体。
- 正在创建翻译。
- i18n 的 table 没有附加 sluggable 行为,因此它不知道何时在标题/名称等翻译字段上发出 sluggable 行为
我想到的解决方案可能是并且已经测试过:
您在实体中指定了受保护的 属性,例如:
protected $_sluggable = 'title';
然后你创建一个 getter:
public function _getSluggableField() {
return $this->_sluggable;
}
完成后,您需要更新供应商文件:
vendor/cakephp/cakephp/src/ORM/Behavior/TranslateBehavior.php
并更改:
foreach ($translations as $lang => $translation) {
foreach ($fields as $field) {
if (!$translation->isDirty($field)) {
continue;
}
$find[] = ['locale' => $lang, 'field' => $field, 'foreign_key' => $key];
$contents[] = new Entity(['content' => $translation->get($field)], [
'useSetters' => false
]);
}
}
至:
foreach ($translations as $lang => $translation) {
foreach ($fields as $field) {
if($field==='slug' && (method_exists($entity, '_getSluggableField') && $entity->_getSluggableField())) {
$translation->set('slug', \Cake\Utility\Text::slug($translation->get($entity->_getSluggableField())));
}
if (!$translation->isDirty($field)) {
continue;
}
$find[] = ['locale' => $lang, 'field' => $field, 'foreign_key' => $key];
$contents[] = new Entity(['content' => $translation->get($field)], [
'useSetters' => false
]);
}
}
我希望有人有更好的解决方案。但这一个很有魅力。
您可以为翻译 table 创建并使用具体的 table class,然后您可以在其中创建 slug。
默认情况下,翻译行为用于查找 table classes 的名称是 I18n
,因此如果您希望将其应用于所有已翻译的 table s,创建 App\Model\Table\I18nTable
,或者如果您希望它仅应用于特定翻译的 tables,请创建单独的数据库翻译 table 和 class,并相应地配置翻译行为通过 translationTable
选项:
// looks up `App\Model\Table\CustomI18nTable`
'translationTable' => 'CustomI18n'
另见
我想我找到了更好的解决方案:
在我的 SluggableBehavior class 中,我更新了行为以包含翻译:
public function beforeSave(Event $event, EntityInterface $entity) {
$this->slug($entity);
if($entity->get('_translations')) {
foreach($entity->get('_translations') as $key=>$translation) {
$this->slug($translation);
}
}
}
当然,很简单,它不需要单独的 table :-) 但是谢谢@ndm。
如果你曾经遇到过一个问题,当你不能在翻译的字段上发出一个 sluggable 行为时,我觉得是的。
每当您为实体保存翻译时,'slug' 属性 将被省略,因为在保存翻译实体时它不是脏的。
- 您保存了一个实体。
- 正在创建翻译。
- i18n 的 table 没有附加 sluggable 行为,因此它不知道何时在标题/名称等翻译字段上发出 sluggable 行为
我想到的解决方案可能是并且已经测试过:
您在实体中指定了受保护的 属性,例如:
protected $_sluggable = 'title';
然后你创建一个 getter:
public function _getSluggableField() {
return $this->_sluggable;
}
完成后,您需要更新供应商文件:
vendor/cakephp/cakephp/src/ORM/Behavior/TranslateBehavior.php
并更改:
foreach ($translations as $lang => $translation) {
foreach ($fields as $field) {
if (!$translation->isDirty($field)) {
continue;
}
$find[] = ['locale' => $lang, 'field' => $field, 'foreign_key' => $key];
$contents[] = new Entity(['content' => $translation->get($field)], [
'useSetters' => false
]);
}
}
至:
foreach ($translations as $lang => $translation) {
foreach ($fields as $field) {
if($field==='slug' && (method_exists($entity, '_getSluggableField') && $entity->_getSluggableField())) {
$translation->set('slug', \Cake\Utility\Text::slug($translation->get($entity->_getSluggableField())));
}
if (!$translation->isDirty($field)) {
continue;
}
$find[] = ['locale' => $lang, 'field' => $field, 'foreign_key' => $key];
$contents[] = new Entity(['content' => $translation->get($field)], [
'useSetters' => false
]);
}
}
我希望有人有更好的解决方案。但这一个很有魅力。
您可以为翻译 table 创建并使用具体的 table class,然后您可以在其中创建 slug。
默认情况下,翻译行为用于查找 table classes 的名称是 I18n
,因此如果您希望将其应用于所有已翻译的 table s,创建 App\Model\Table\I18nTable
,或者如果您希望它仅应用于特定翻译的 tables,请创建单独的数据库翻译 table 和 class,并相应地配置翻译行为通过 translationTable
选项:
// looks up `App\Model\Table\CustomI18nTable`
'translationTable' => 'CustomI18n'
另见
我想我找到了更好的解决方案:
在我的 SluggableBehavior class 中,我更新了行为以包含翻译:
public function beforeSave(Event $event, EntityInterface $entity) {
$this->slug($entity);
if($entity->get('_translations')) {
foreach($entity->get('_translations') as $key=>$translation) {
$this->slug($translation);
}
}
}
当然,很简单,它不需要单独的 table :-) 但是谢谢@ndm。