Cakephp,i18n,检索相关模型的翻译记录

时间:2010-03-25 12:00:38

标签: cakephp internationalization has-and-belongs-to-many

引用cakephp Book(ver 1.3):

  

请注意,只会翻译您直接执行find的模型字段。通过关联附加的模型将不会被翻译,因为目前不支持在关联模型上触发回调。

有没有人为此提出解决方案?

如果没有,你可以给我一些关于以下简单场景的指示。

我有2个型号:

项目,类别。
项目HABTM类别

我已经正确设置了i18n表,并且我在数据库中有一些条目,全部已翻译。当我检索一个项目时,它确实检索了翻译而不是翻译的类别,因为正如在cakephp中所说的那样,通过关联附加的模型将不会被翻译。

4 个答案:

答案 0 :(得分:3)

我有另一种解决方法;我不知道它是否更好或更差的性能或风格,只是它适合“胖模型,瘦的控制器”的目标:

<强> AppModel.php

public function getTranslatedModelField($id = 0, $field) {

        $res = false;

        $db = $this->getDataSource();
        $tmp = $db->fetchAll('SELECT content from s2h_i18n WHERE model = ? AND locale = ? AND foreign_key = ? AND field = ? LIMIT 1',
            array($this->alias, Configure::read('Config.language'), $id, $field)
        );      
        if (!empty($tmp)) {
            $res = $tmp[0]['s2h_i18n']['content'];
        }
        return $res;
}

<强> SomeModel.php

   public function afterFind($results, $primary = false) {

        foreach ($results as $key => $val) {
            if (isset($val['SomeOtherModel']) && isset($val['SomeOtherModel']['id'])) {
                $results[$key]['SomeOtherModel']['name'] = 
    $this->SomeOtherModel->getTranslatedModelField($val['SomeOtherModel']['id'], 'name');
            }
            // other possible queries for other models and/or fields
         }

        return $results;
    }

答案 1 :(得分:0)

好的,我找到了解决方案。这主要是一种解决方法。我应该早点想到这一点。

我正在做的是以下内容。我发现所有项目和递归所有与项目相关的类别。现在,因为cakephp没有翻译类别,所以我使用的是初始查询的结果,我只针对类别执行第二个,但是使用了我在第一个查询中找到的类别ID值。现在,cakephp翻译类别,因为我只搜索它们,我可以翻译他们的数据。

目前我对这个解决方案没问题,但是如果第一个cakephp使翻译行为开箱即用,或者如果有人的行为可以支持在相关模型上检索翻译,那就太好了。

答案 2 :(得分:0)

我稍微概括了afterFind部分,以便它自动抓取要从关联模型的actsAs["Translate"]数组转换的字段,并使用一组相关模型来(可能)转换:< / p>

public function afterFind($results, $primary = false){

    $modelsToTranslate = array("SomeModel", "AnotherModel");

    foreach ($results as $key => $val){
        foreach($modelsToTranslate as $mtt){
            if (isset($val[$mtt])){
                foreach($val[$mtt] as $fieldname => $fieldval){
                    foreach ($this->$mtt->actsAs["Translate"] as $fieldToTranslate){
                        $results[$key][$mtt][$fieldname][$fieldToTranslate] = $this->$mtt->getTranslatedModelField($val[$mtt][$fieldname]['id'], $fieldToTranslate);
                    }
                }            
            }               
        }
    }
    return $results;
}

答案 3 :(得分:0)

我采用了上面的解决方案并稍微概括了两个函数,现在它需要与translate行为一起使用,并且这两个函数都需要进入model.php - 其他一切都应该自行运行:

public function getTranslatedModelField($id = 0, $field) {
    $res = false;
    $translateTable = (isset($this->translateTable))?$this->translateTable:"i18n";

    $db = $this->getDataSource();
    $tmp = $db->fetchAll(
        "SELECT content from {$translateTable} WHERE model = ? AND locale = ? AND foreign_key = ? AND field = ? LIMIT 1",
        array($this->alias, Configure::read('Config.language'), $id, $field)
    );
    if (!empty($tmp)) {
        $res = $tmp[0][$translateTable]['content'];
    }
    return $res;
}   

public function afterFind($results, $primary = false) {

    if($primary == false && array_key_exists('Translate', $this->actsAs)) {
        foreach ($results as $key => $val) {
            if (isset($val[$this->name]) && isset($val[$this->name]['id'])) {
                foreach($this->actsAs['Translate'] as $translationfield) {  
                    $results[$key][$this->name][$translationfield] = 
                    $this->getTranslatedModelField($val[$this->name]['id'], $translationfield);
                }
            } else if($key == 'id' && is_numeric($val)) {
                foreach($this->actsAs['Translate'] as $translationfield) {  
                    $results[$translationfield] = 
                    $this->getTranslatedModelField($val, $translationfield);
                }                   
            }
         }
    }

    return $results;
}