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

Database 如何在多语言数据库模型中使用Yii?,database,multilingual,yii,Database,Multilingual,Yii,我从我创建的数据库中获取数据时遇到了一个问题,我创建的数据库完全是多语言的,我希望这里的人能帮助我 我把所有的桌子分成两部分;“通用”表(不包含任何需要翻译的文本)和包含所有需要翻译的字段的表 示例表: base_material id picture base_material_i18n base_material_id localization_id name description review_status review_n

我从我创建的数据库中获取数据时遇到了一个问题,我创建的数据库完全是多语言的,我希望这里的人能帮助我

我把所有的桌子分成两部分;“通用”表(不包含任何需要翻译的文本)和包含所有需要翻译的字段的表

示例表:

base_material
    id
    picture
base_material_i18n
    base_material_id
    localization_id
    name
    description
    review_status
    review_notes
localization
    id
    language_name
查询以获取翻译(如果没有可用的翻译,则使用英语(en)作为后备语言):

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

使用我需要的现有系统的一个示例是:

你知道怎么做吗?我检查了关于多语言站点的现有Yii扩展(如),但它们都使用不同的数据库设计(主表中的常规信息+回退语言,i18n表中的翻译),我不确定如何更改这些扩展以使用我的DB模型

如果有人知道一种方法来改变现有的扩展,使它可以使用我的DB方案,那么这将是绝对明智的,而且可能是最好的方法

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

编辑:查看了98次,但只有3次赞成票和1条评论。无论是在我的问题中还是在应用程序/数据库设计中,我都忍不住觉得自己做错了什么;或者我的问题非常独特(这会让我吃惊,因为我不认为我的多语言数据库设计是那么荒谬;-)。因此,如果有人知道使用Yii和/或Propel(除了当前由于文本字段重复而不喜欢的扩展)或类似功能的多语言网站的更好的全面解决方案,也请让我知道


提前谢谢

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

下面的解决方案没有自定义SQL语句,但我认为这可以通过关系参数实现,无论如何,如果您使用数据库中的外键(例如MySQL InnoDB),gii将在基本材质和基本材质表之间创建关系,如

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

要找到所需的i18n记录还有很多工作要做,您还可以进一步限制with()选项,以提高性能并减少PHP端的解析

但可能存在不同的用例如何确定值,例如所有翻译、翻译或回退、无回退(空值)。 这里的场景可能会有所帮助

附言:我会去参加一个聚会的

您是否尝试过(基于)

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


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

您可以尝试使用简单的多语言CRUD扩展。 它的使用和修改非常简单。您只需要将语言字段添加到表中。 请看这里的描述:
它是在阿尔法州,但尝试了几个项目。您可以很容易地修改它,或者联系作者来修复或添加功能

如果还有任何关于为什么或什么的问题,或者如果有什么不完全清楚,只需问:-)抱歉,您很难找到答案。如果可以的话,我会尽力帮忙的。因此,基本上,您只需要一个查询,在该项的翻译语言不存在的情况下,为任何值选择所选的翻译和英语,对吗?我想先确定我理解了你的问题;)嗨,Chiramusi,谢谢你的帮助。我在问题中发布的查询在我的数据库中运行时有效,但我想知道如何更“自动”地执行。我链接到的扩展以自动化的方式向模型添加了翻译,我希望我的数据库有类似的功能(扩展使用不同的db方案),或者我想知道如何更改扩展以使用我的表和设计。否则,如果您知道一种将Propel与Yii一起使用的方法,那也太好了(因为Propel内置了这种数据库翻译)。事实上,该查询非常适合您的答案schmunk!事实上,你答案的第二部分或多或少就是我想要的。第一部分我完全理解并且可以工作,但是对于所有表和所有字段来说太麻烦了。很明显,你比我有更多的Yii经验;有没有可能详细介绍一下这个基类?我知道你想做什么,但我不知道该怎么做,只是创造了一种行为。我发现通过t()方法访问翻译会更干净。让我们看看这个看起来很漂亮
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();
}