我在从我创建的数据库中获取完全多语言的数据时遇到问题,我希望有人可以帮助我。
我将所有桌子分成两部分; “通用”表(不包含任何需要翻译的文本)和包含需要翻译的所有字段的表格。
示例表:
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多语言网站的更好的全方位解决方案(除了由于文本字段的重复而我真的不喜欢的当前扩展)或类似的东西,请告诉我同样。
提前致谢!
答案 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();
}
要找到所需的i18n记录还有很多工作要做,还可以进一步限制with()选项以提高性能并减少PHP方面的解析。
但是可能有不同的用例如何确定值,例如所有翻译,翻译或后备,没有后备(空值)。 场景在这里可能会有所帮助。
PS:我会选择github project!
答案 2 :(得分:0)
您可以尝试使用简单的多语言CRUD扩展程序。 它的使用和修改非常简单。你只需要在你的表中添加语言字段。 只需在此处观看说明:http://all-of.me/yii-multilingual-crud/ 它处于alpha状态,但尝试过几个项目。您可以轻松地修改它或联系作者来修复或添加功能