Cakephp、i18n、检索关联模型的翻译记录

发布于 2024-08-26 16:56:59 字数 342 浏览 9 评论 0原文

引用 cakephp 书(1.3 版):

请注意,只有您直接进行查找的模型字段才会被翻译。通过关联附加的模型不会被转换,因为当前不支持触发关联模型的回调。

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

如果没有,您能给我一些关于以下简单场景的指示吗?

我有 2 个模型:

项目、类别。
项目 HABTM 类别

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

Quoting from the cakephp Book (ver 1.3):

Note that only fields of the model you are directly doing find on will be translated. Models attached via associations won't be translated because triggering callbacks on associated models is currently not supported.

Has anyone come up with a solution for this?

If not could you give me some pointers concerning the following simple scenario.

I have 2 models:

Project, Category.
Project HABTM Category

I have properly set up i18n table and I have a few entries in the db, all translated. When I retrieve a project it does retrieve the translation but not the translated category because as it says in the cakephp book models attached via associations won't be translated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夜司空 2024-09-02 16:56:59

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

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;
    }

I have another workaround; I don't know if it is any better or worse performance- or style-wise, only that it suits the "fat models, skinny controllers" goal:

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;
    }
无边思念无边月 2024-09-02 16:56:59

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

我正在做的事情如下。我正在查找所有项目以及与项目相关的递归所有类别。现在,由于 cakephp 不翻译类别,我正在使用初始查询的结果,并且我仅针对类别执行第二个查询,但使用我在第一个查询中找到的类别 id 值。现在 cakephp 可以翻译类别,因为我只是搜索它们并且可以翻译它们的数据。

目前我对这个解决方案很满意,但如果首先 cakephp 能够开箱即用地准备好翻译行为,或者其次如果有人有可以支持在关联模型上检索翻译的行为,那就太好了。

OK I found a solution. Which is mostly a workaround. I should have thought of that earlier.

What I'm doing is the following. I'm finding all projects and recursively all categories associated with projects. Now since cakephp does not translate categories I am using the results from the initial query and I am performing a second one only for categories but using the category id values that I found on the first query. Now cakephp translates categories since I'm only searching for them and I can have their data translated.

At the moment I'm OK with this solution but it would be nice if first cakephp makes the translate behavior out of the box ready or secondly if someone had a behavior that could support retrieval of translation on associated models.

不可一世的女人 2024-09-02 16:56:59

我稍微概括了 afterFind 部分,以便它自动从关联模型的 actsAs["Translate"] 数组中获取要翻译的字段,并使用关联的数组模型(可能)翻译:

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;
}

I generalized the afterFind part a bit, so that it automatically grabs the fields to translate from the associated models' actsAs["Translate"] array, and uses an array of associated models to (potentially) translate:

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;
}
月野兔 2024-09-02 16:56:59

我采用了上述解决方案并对这两个函数进行了一些概括,现在它需要与翻译行为一起使用,并且这两个函数都需要进入 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;
}   

I took above solution and generalized both functions a bit, now it needs to be used together with the translate behaviour and both functions need to go into the model.php - everything else should work by itself:

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;
}   
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文