如何使用Yii与多语言数据库模型? [英] How to use Yii with a multilingual database model?

查看:132
本文介绍了如何使用Yii与多语言数据库模型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从数据库获取数据时遇到问题,我创建的数据库完全是多语言的,我希望有人能帮助我。



分割我的所有表2分; 通用表(不包含任何需要翻译的文本)以及包含需要使用翻译翻译的所有字段的表。



示例表格:

  base_material 
id
picture
base_material_i18n
base_material_id
localization_id
name
description
review_status
review_notes
本地化
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'

我的问题是如何自动获得这些翻译(用这个查询中的后退语言)我的模型在Yii当我正在寻找base_material对象? (这只是一个示例表,但几乎所有的表(20+)都是用这种方式构建的,所以如果可能的话我需要一些灵活的)



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



任何想法如何去做那?我查看了有关多语种网站的现有Yii扩展(例如多语言活动记录) ,但它们都使用不同的数据库设计(主表中的一般信息+后退语言,i18n表中的翻译),我不知道如何更改这些扩展以使用我的DB模型。 p>

如果有人知道一个方法来改变现有的扩展,所以它可以使用我的DB方案,那将是绝对辉煌,可能是最好的方式做到这一点。 / p>

编辑:我添加了一个赏金,因为我仍然找不到任何东西,如何让Propel使用Yii(确实存在一个Doctrine的扩展,但Doctrine不支持这种带有翻译的数据库模型),也没有任何关于如何使用现有Yii扩展或范围处理这些数据的信息。



编辑:观看次数为98次,但只有3次upvote和1次评论。我不禁感觉我在这里做错了,无论是在我的问题或应用程序/数据库设计;这或者我的问题只是非常独特(这将使我惊讶,因为我不认为我的多语言数据库设计是荒谬的;-)。所以,如果有人知道一个更好的全面的解决方案多语言网站与Yii和/或Propel(除了当前的扩展,我真的不喜欢由于文本字段的重复)或类似的东西,请让我知道



提前感谢!

解决方案

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



以下解决方案没有自定义SQL语句,但我认为这可以用关系params实现,反正,如果你使用外键在你的数据库(例如MySQL InnoDB)gii将创建base_material和base_material_i18n表之间的关系,如



class BaseMaterial extends CActiveRecord

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



class BaseMaterialI18n extends CActiveRecord

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

现在您可以使用对象符号来访问您的翻译关系。

  $ model = BaseMaterial :: model() - > with('baseMaterialI18ns') - > findByPk ); 
foreach($ model-> baseMaterialI18ns AS $ translation){
if($ translation-> language!=我需要的语言)continue:
// data ...
}

我想过为这些模型创建一个行为或基类它将作为管理翻译的助手 - 伪代码:

  I18nActiveRecord扩展CActiveRecord 

protected $ _attributesI18n;

//在查询上填充_attributesI18n ...

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项目


I’m having a problem getting the data from my database which I created to be completely multilingual, and I hope someone here can help me.

I’ve split up all my tables in 2 parts; the "universal" table (does not contain any text that needs to be translated) and the table which contains all the fields that need to be translated with their translations.

Example tables:

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

Query to get the translations (using English (en) as a fall-back language if there is no translation available):

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'

My question is how I can automatically get those translations (with the fall-back language as in this query) attached to my model in Yii when I’m searching for the base_material objects? (This is only 1 example table, but almost all my tables (20+) are built in this way, so if possible I would be needing something flexible)

An example of an existing system using what I would need is Propel: http://propel.posterous.com/propel-gets-i18n-behavior-and-why-it-matters

Any ideas how to go about doing that? I’ve checked the existing Yii extensions regarding multilingual sites (like Multilingual Active Record), but they all use a different database design (general information+fall-back language in the main table, translations in the i18n table), and I’m not sure how to change those extensions to use my kind of DB model.

If someone knows of a way to change that existing extension so it can use my kind of DB scheme, then that would be absolutely brilliant and probably the best way to do this.

Edit: I've added a bounty because I still can't find anything on how to let Propel work with Yii (there does exist an extension for Doctrine, but Doctrine doesn't support this kind of DB model with translations either), nor any more information as to how to deal with this using an existing Yii extension or with scopes.

Edit: 98 times viewed but only 3 upvotes and 1 comment. I can't help feeling like I'm doing something wrong here, be it in my question or application/database design; either that or my problem is just very unique (which would surprise me, as I don't think my multilingual database design is that absurd ;-). So, if anyone knows of a better all-round solution for multilingual sites with Yii and/or Propel (apart from the current extensions which I really don't like due to the duplication of text fields) or something similar, please let me know as well.

Thanks in advance!

解决方案

I am also looking for a generic solution to implement i18n into Yii models. Recently I chose a very similar database schema for a project like you. The only difference is, that I am not using a separate language table, I store the language information in the i18n table.

The following solution is without a custom SQL statement, but I think this could be implemented with relation params, anyway, if you're working with foreign key in your database (eg. MySQL InnoDB) gii will create relations between your base_material and base_material_i18n table, like

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'),
    );
}

Now you'd be able to access your translations by using the object notation for relations.

$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 ...
}

I thought about creating a behavior or base class for those models which would act a as helper for managing the translations - pseudo code:

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

There is more work to be done to find the needed i18n record, also you could further limit the with() option to improve performance and reduce parsing on the PHP side.

But there may be different use cases how to determine the value, e.g. all translations, translation or fallback, no fallback (empty value). Scenarios could be helpful here.

PS: I would be up for a github project!

这篇关于如何使用Yii与多语言数据库模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆