如何使用Yii多语言数据库模型?

时间:2011-10-31 16:21:04

标签: database multilingual 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),但它们都使用不同的数据库设计(主表中的一般信息+后备语言,i18n表中的翻译),以及我不确定如何更改这些扩展以使用我的数据库模型。

如果有人知道改变现有扩展的方法,以便它可以使用我的数据库方案,那么这将是绝对精彩的,可能是最好的方法。

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

修改:已查看98次但只有3次upvotes和1次评论。我不禁感到我在这里做错了,无论是在我的问题还是应用程序/数据库设计中;或者我的问题只是非常独特(这会让我感到惊讶,因为我不认为我的多语种数据库设计是荒谬的;-)。所以,如果有人知道Yii和/或Propel多语言网站的更好的全方位解决方案(除了由于文本字段的重复而我真的不喜欢的当前扩展)或类似的东西,请告诉我同样。

提前致谢!

3 个答案:

答案 0 :(得分:4)

您是否尝试过http://www.yiiframework.com/extension/i18n-columns/(基于http://www.yiiframework.com/extension/stranslateablebehavior/)?

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

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

答案 1 :(得分: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

答案 2 :(得分:0)

您可以尝试使用简单的多语言CRUD扩展程序。 它的使用和修改非常简单。你只需要在你的表中添加语言字段。 只需在此处观看说明:http://all-of.me/yii-multilingual-crud/ 它处于alpha状态,但尝试过几个项目。您可以轻松地修改它或联系作者来修复或添加功能