CakePHP actAs Translate和$ Model :: find()

时间:2012-09-27 16:20:58

标签: cakephp translate

我已将Translate行为附加到我的某个模型中,我对此有一些缺点:

1)如果我在将行为附加到模型时不将数据保存在作为参数传递的所有字段中,则$ Model :: find()方法不会获取插入的行。

public $actsAs = array(
    'Translate' => array(
        'title' => 'title_Translation',
        'description' => 'description_Translation',
        'description_long' => 'description_long_Translation'
    )
);

例如:如果我仅向$Model::save()方法传递'title'的值,则即使在i18n表中也会保存数据,但$Model::find()没有得到任何结果。我必须传递所有字段的数据。

我可以强制它检索这些记录吗?

2)如何获取应用程序管理员端的所有记录(无论保存记录的语言),以便列出它们以便用户可以更改它(编辑数据,保存多个数据)语言)?现在,我只能获得与当前语言相对应的记录(从Configure中读取或显式设置)..

谢谢!

3 个答案:

答案 0 :(得分:4)

我解决了这个问题,我将TranslateBehavior复制到app / Model / Behavior(只是为了避免将来的升级出现问题并保留原来的一个以防万一)然后我改变了行为的_addJoin(...)方法,只是在第255行将连接类型从INNER更改为LEFT(我使用的是蛋糕2.2.3)。

现在,如果存在记录,则始终会检索它,即使缺少已翻译的字段。

除了需要检查翻译字段是否为空之外,不要看到任何缺点。

答案 1 :(得分:2)

好吧,我可能会有点迟到,但无论如何......

1)Cake在获取行时使用INNER JOIN并且它是相关的翻译,所以基本上没有简单的方法。你必须确保每次都保存每个可翻译的字段 - 即使你只是将它保存为空白。唯一的选择是围绕核心进行黑客攻击,使其使用左连接而不是内连接 - 但不要这样做。

2)该手册解释了如何在此处获取所有记录:http://book.cakephp.org/2.0/en/core-libraries/behaviors/translate.html#retrieve-all-translation-records-for-a-field

现在,大多数情况下您可能只希望获得一次翻译,因此您不希望在模型中修改$ actsAs ['Translate']数组的定义。所以我做了,在AppModel.php中设置了一个方法,它可以动态修改$ actsAs ['Translate']数组:

/*  
 * See http://book.cakephp.org/2.0/en/core-libraries/behaviors/translate.html#using-the-bindtranslation-method
 * This is for making it so we fetch all translations, as opposed to just that of the current locale.
 * Used for eg. editing (multiple translations) via the admin interface.
 */
public function bindAllTranslations(){
    $translatableFields = $this->actsAs['Translate'];

    $keyValueFields = array();
    foreach($translatableFields as $field){
        $keyValueFields[$field] = $field.'Translation';
    }

    $this->bindTranslation($keyValueFields,false);  // false means it will be changed for all future DB transactions in this page request - and won't be reset after the next transaction.
}

因此,如果它是一个管理方法(或您想要所有翻译的任何其他情况),您在进行查找之前调用该代码:

$this->MyModel->bindAllTranslations();
$this->MyModel->find('all');

希望有所帮助!

答案 2 :(得分:0)

非常感谢eleonzx,我十年来一直遇到这个问题,而你的简单回答我现在可以继续前进!再次感谢。

也许这段代码可以帮助很多人:

在我的AppController beforeFilter方法中我调用_setLanguage

private function _setLanguage() {
    if($this->Session->read('Config.language')){
        $locale = $this->Session->read('Config.language');
        $this->{$this->modelClass}->setLocale($locale);
    }else{
        $this->{$this->modelClass}->Behaviors->disable('Translate');
    }
}

使用else条件,如果会话中没有设置语言环境,我会动态禁用翻译行为以获取原始内容(我使用基本链接在语言之间切换)。