如何在 CakePHP 中使翻译字段可滑动 3.x

How do you make a translation field sluggable in CakePHP 3.x

如果你曾经遇到过一个问题,当你不能在翻译的字段上发出一个 sluggable 行为时,我觉得是的。

每当您为实体保存翻译时,'slug' 属性 将被省略,因为在保存翻译实体时它不是脏的。

  1. 您保存了一个实体。
  2. 正在创建翻译。
  3. 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。