2011-10-31 54 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狀態,但在幾個項目上試過。你可以很容易地修改它或聯繫作者修復或添加功能