2011-10-31 90 views
11

我在从我的数据库中获取数据时遇到问题,我创建的数据完全是多语言的,我希望这里有人能帮助我。如何在多语言数据库模型中使用Yii?

我把所有的表格分成两部分, “通用”表(不包含任何需要翻译的文本)以及包含需要翻译的所有字段的表。

示例表:

base_material 
    id 
    picture 
base_material_i18n 
    base_material_id 
    localization_id 
    name 
    description 
    review_status 
    review_notes 
localization 
    id 
    language_name 

查询来获取翻译(使用英语(en)作为后备语言,如果没有可用的翻译):

SELECT o.id 
    , o.type 
    , o.code 
    , o.position 
    , ifnull(t.name,d.name) name 
    , ifnull(t.description,d.description) description 
    FROM base_material o 
     INNER JOIN base_material_i18n d 
       ON (o.id=d.base_material_id) 
     LEFT OUTER JOIN base_material_i18n t 
        ON (d.base_material_id=t.base_material_id AND t.localization_id='nl') 
WHERE d.localization_id='en' 

我的问题是如何当我搜索base_material对象时,我可以自动将这些翻译(在此查询中使用后退语言)附加到Yii中的模型中? (这只是一个示例表,但几乎所有我的表(20+)都是以这种方式构建的,所以如果可能的话,我会需要灵活的东西)

使用我需要的现有系统的示例是Propel :http://propel.posterous.com/propel-gets-i18n-behavior-and-why-it-matters

任何想法如何去做呢?我已经检查了关于多语言站点的现有Yii扩展(如Multilingual Active Record),但它们都使用不同的数据库设计(主表中的一般信息+回退语言,国际化表中的翻译),我不确定如何更改这些扩展以使用我的数据库模型。

如果有人知道改变现有扩展的方法,以便它可以使用我的数据库方案,那么这将是绝对的辉煌,也许是最好的方式来做到这一点。

编辑:我添加了一个赏金,因为我仍然无法找到关于如何让Propel与Yii协同工作的任何内容(它确实存在对Doctrine的扩展,但Doctrine不支持这种带有翻译的DB模型也没有关于如何使用现有的Yii扩展或范围来处理这个问题的更多信息。

编辑:98次浏览,但只有3上传和1评论。我不禁感到自己在这里做错了什么,无论是在我的问题还是应用程序/数据库设计中;无论是我的问题还是我的问题都非常独特(这会让我感到惊讶,因为我不认为我的多语言数据库设计是荒谬的;-)。因此,如果有人知道Yii和/或Propel的多语言站点更好的全面解决方案(除了由于文本字段的重复,我真的不喜欢的当前扩展)或类似的东西,请告诉我以及。

在此先感谢!

+0

如果有任何更多的问题关于为什么或什么,或者如果有什么不完全清楚,只要问:-) – Xuntar

+1

对不起,你有这样一个很难找到答案。如果可以,我会尽力帮忙。所以基本上你只想要一个查询选择翻译和英语的任何值,其中该项目的翻译语言不存在的权利?我想确定我首先理解你的问题;) – Chiramisu

+0

Hi Chiramusi,感谢您的帮助。我在我的问题中发布的查询在我的数据库中运行时发挥作用,但我想知道如何更“自动地”执行此操作。我已经链接到的扩展以自动方式将模型翻译添加到模型中,我想为我的数据库(扩展使用不同的数据库模式)提供类似的东西,或者想知道如何更改该扩展以使用我的表格和设计。否则,如果你知道用Yii来使用Propel的方法,那么它也会很棒(因为Propel有这种内置的数据库转换)。 – Xuntar

回答

2

我也在寻找一个通用的解决方案来实现i18n进入Yii模型。 最近,我为像你这样的项目选择了一个非常类似的数据库模式。 唯一的区别是,我没有使用单独的语言表,我将语言信息存储在i18n表中。

以下解决方案没有自定义SQL语句,但我认为这可以用关系参数来实现,无论如何,如果您在数据库中使用外键(例如。MySQL的InnoDB的)GII将创建base_material和base_material_i18n表之间的关系,就像

class BaseMaterial extends CActiveRecord 

public function relations() 
{ 
    return array(
     'baseMaterialI18ns' => array(self::HAS_MANY, 'base_material_i18n', 'id'), 
    ); 
} 



class BaseMaterialI18n extends CActiveRecord 

public function relations() 
{ 
    return array(
     'baseMaterial' => array(self::BELONGS_TO, 'base_material', 'id'), 
    ); 
} 

现在,你可以通过使用对象表示法的关系来访问您的翻译。

$model = BaseMaterial::model()->with('baseMaterialI18ns')->findByPk(1); 
foreach($model->baseMaterialI18ns AS $translation) { 
    if ($translation->language != "the language I need") continue: 
    // do something with translation data ... 
} 

我想到了创建这将扮演一个作为辅助管理翻译这些模型行为或基类 - 伪代码:

I18nActiveRecord extends CActiveRecord 

protected $_attributesI18n; 

// populate _attributesI18n on query ... 

public function __get($name) { 
    if(isset($this->_attributesI18n['language_I_need'][$name])) 
    return $this->_attributesI18n[$name]; 
    else if(isset($this->_attributesI18n['fallback_language'][$name])) 
    return $this->_attributesI18n[$name]; 
    else 
    parent::__get(); 
} 

CActiveRecord __get() source

还有更多的工作为了找到需要的i18n记录,还可以进一步限制with()选项以提高性能并减少PHP侧的解析。

但是,如何确定数值可能有不同的用例,例如,所有翻译,翻译或后备,无后备(空值)。 情景在这里可能会有所帮助。

PS:我会为github project

+0

谢谢你的回答schmunk! 事实上,你的答案的第二部分或多或少是我所期待的。第一部分我完全理解并且能够工作,但对于所有表格和所有领域来说太麻烦了。 显然你对Yii的经验比我多;是否有可能在该基类上详细阐述一下?我了解你想要做什么,但没有得知如何真正做到这一点。 – Xuntar

+2

刚刚为此创建了一个行为。我发现如果通过t()方法访问翻译,它会更干净。让我们来看看https://github.com/schmunk42/p3extensions/blob/master/behaviors/P3TranslationBehavior.php – schmunk

+0

这看起来很精彩,谢谢你让我(和这个问题)更新!我想我明白它是如何工作的,以及如何使用它,我应该可以在明天晚上试用它。我假设'relation'=>'daContentTranslations'会在你的答案中使用示例代码的第一部分变成'relation'=>'baseMaterialI18ns'?如果我在我的所有桌子上使用相同的关系名称,那么这对所有桌子都适用?再次;非常感谢! – Xuntar

4

你试过http://www.yiiframework.com/extension/i18n-columns/(根据http://www.yiiframework.com/extension/stranslateablebehavior/)?

这是一种替代,简单的方法,方法是在{field} _ {language code}样式中添加新的表格字段,然后将原始模型中的翻译字段设置为当前语言在afterFind上的翻译。

从本质上讲,它可以帮助你启动并运行可翻译的字段,翻译的内容可以“自动”获取,好的和不好的:)。添加和删​​除语言(=列)使用迁移完成。

+0

为什么没有人对此回复表示嗨? –

0

您可以尝试使用简单的多语言CRUD扩展。 它使用和修改非常简单。你只需要添加语言字段到你的表。 只是看看这里的描述:http://all-of.me/yii-multilingual-crud/ 它处于alpha状态,但在几个项目上试过。你可以很容易地修改它或联系作者修复或添加功能

相关问题