2011-10-31 8 views
11

Ho riscontrato un problema nel recuperare i dati dal mio database che ho creato per essere completamente multilingue e spero che qualcuno qui mi possa aiutare.Come utilizzare Yii con un modello di database multilingue?

Ho diviso tutti i miei tavoli in 2 parti; la tabella "universale" (non contiene alcun testo che deve essere tradotto) e la tabella che contiene tutti i campi che devono essere tradotti con le loro traduzioni.

tabelle Esempio:

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

query per ottenere le traduzioni (usando l'inglese (en) come lingua di ripiego se non v'è alcuna traduzione disponibile):

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' 

mia domanda è come Posso ottenere automaticamente quelle traduzioni (con la lingua di ripiego come in questa query) allegate al mio modello in Yii quando cerco gli oggetti base_material? (Questa è solo una tabella di esempio, ma quasi tutti i miei tavoli (20+) sono costruiti in questo modo, quindi se possibile avrei bisogno di qualcosa di flessibile)

Un esempio di un sistema esistente che utilizza quello di cui avrei bisogno è Propel : http://propel.posterous.com/propel-gets-i18n-behavior-and-why-it-matters

Qualche idea su come procedere? Ho controllato le estensioni Yii esistenti relative a siti multilingue (come Multilingual Active Record), ma tutte usano un design di database diverso (informazioni generali + lingua fall-back nella tabella principale, traduzioni nella tabella i18n), e non sono sicuro come cambiare quelle estensioni per usare il mio tipo di modello DB.

Se qualcuno conosce un modo per modificare l'estensione esistente in modo che possa utilizzare il mio tipo di schema DB, sarebbe assolutamente geniale e probabilmente il modo migliore per farlo.

Edit: Ho una taglia perché ancora non riesco a trovare nulla su come lasciare il lavoro Propel con Yii (vi esiste un'estensione per dottrina, ma Dottrina non supporta questo tipo di modello di DB con traduzioni entrambi), né ulteriori informazioni su come gestirlo utilizzando un'estensione Yii esistente o con scope.

Modifica: 98 volte visualizzato ma solo 3 upvotes e 1 commento. Non posso fare a meno di pensare che sto facendo qualcosa di sbagliato qui, sia nella mia domanda o nella progettazione di applicazioni/database; o quello o il mio problema è solo molto singolare (il che mi sorprenderebbe, poiché non penso che il mio design di database multilingue sia così assurdo ;-). Quindi, se qualcuno conosce una soluzione a tutto tondo per siti multilingue con Yii e/o Propel (a parte le estensioni attuali che non mi piacciono molto a causa della duplicazione dei campi di testo) o qualcosa di simile, per favore fatemi sapere anche.

Grazie in anticipo!

+0

Se ci sono altre domande sul perché o su cosa, o se qualcosa non è del tutto chiaro, basta chiedere :-) – Xuntar

+1

Mi dispiace che tu stia avendo un tale difficile trovare una risposta. Cercherò di aiutare se posso. Quindi in pratica vuoi solo una query che scelga la traduzione selezionata e l'inglese per qualsiasi valore in cui la lingua tradotta per quell'elemento non esiste giusto? Voglio essere sicuro di aver capito prima la tua domanda;) – Chiramisu

+0

Ciao Chiramusi e grazie per il tuo aiuto. La query che ho postato nella mia domanda funziona quando la eseguo nel mio database, ma mi chiedo come posso farlo più "automagicamente". L'estensione a cui mi sono collegato aggiunge traduzioni al modello in modo automatico e vorrei qualcosa di simile per il mio database (l'estensione usa un diverso schema db) o un'idea su come cambiare quell'estensione per usare le mie tabelle e il mio design. Altrimenti, se si è a conoscenza di un modo di utilizzare Propel con Yii, sarebbe altrettanto utile (poiché Propel ha questo tipo di traduzioni di database integrate). – Xuntar

risposta

2

Sto anche cercando una soluzione generica per implementare i18n nei modelli Yii. Recentemente ho scelto uno schema di database molto simile per un progetto come te. L'unica differenza è che non sto utilizzando una tabella lingua separata, ma memorizzo le informazioni sulla lingua nella tabella i18n.

La seguente soluzione è senza un'istruzione SQL personalizzata, ma penso che questo potrebbe essere implementato con parametri di relazione, comunque, se si sta lavorando con chiave esterna nel database (ad es.MySQL InnoDB) gii creerà i rapporti tra il base_material e tavolo base_material_i18n, come

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

Ora si sarebbe in grado di accedere ai vostri traduzioni utilizzando la notazione oggetto delle relazioni.

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

ho pensato di creare un comportamento o classe di base per quei modelli che agire a come aiuto per la gestione delle traduzioni - pseudo codice:

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

C'è ancora del lavoro da essere fatto per trovare il record i18n necessario, inoltre è possibile limitare ulteriormente l'opzione with() per migliorare le prestazioni e ridurre l'analisi sul lato PHP.

Ma ci possono essere diversi casi d'uso su come determinare il valore, ad es. tutte le traduzioni, traduzioni o fallback, nessun fallback (valore vuoto). Gli scenari potrebbero essere utili qui.

PS: Sarei pronto per un github project!

+0

Grazie per la tua risposta schmunk! In effetti la seconda parte della tua risposta è più o meno ciò che cercherò. La prima parte capisco perfettamente e funzionerebbe, ma è troppo fastidiosa con tutte le tabelle e tutti i campi. Chiaramente hai più esperienza con Yii di me; sarebbe possibile elaborare un po 'su quella classe base? Ho un'idea di quello che cerchi di fare, ma non ho idea di come farlo davvero. – Xuntar

+2

Ho appena creato un comportamento per questo.Ho scoperto che è più pulito se accedete alle traduzioni con un metodo t(). Diamo un'occhiata https://github.com/schmunk42/p3extensions/blob/master/behaviors/P3TranslationBehavior.php – schmunk

+0

Questo sembra geniale, grazie per avermi aggiornato (e questa domanda)! Penso di aver capito il modo in cui funziona e come usarlo e dovrei essere in grado di provarlo domani sera. Presumo che la 'relazione' => 'daContentTranslations' diventi 'relation' => 'baseMaterialI18ns' usando la prima parte del codice di esempio nella tua risposta? E se io uso lo stesso nome di relazione su tutti i miei tavoli, questo funzionerebbe su tutti loro? Ancora; grazie mille! – Xuntar

4

Hai provato http://www.yiiframework.com/extension/i18n-columns/ (basato su http://www.yiiframework.com/extension/stranslateablebehavior/)?

È un approccio alternativo, più semplice, aggiungendo nuovi campi di tabella nello stile di {field} _ {codice lingua} e quindi impostando il campo tradotto nel modello originale nella traduzione della lingua corrente su afterFind.

In sostanza, si otterrà attivo e funzionante con campi traducibili con il contenuto tradotto recuperato "automaticamente", nel bene e nel male :). L'aggiunta e la rimozione di lingue (= colonne) viene eseguita utilizzando le migrazioni.

+0

perché nessun organismo ha risposto ciao a questa risposta? –

0

Si può provare a utilizzare un'estensione CRUD multilingue semplice. è molto semplice da usare e modificare. hai solo bisogno di aggiungere un campo di lingua al tuo tavolo. basta guardare la descrizione qui: http://all-of.me/yii-multilingual-crud/ è in stato alfa, ma provato su alcuni progetti. puoi facilmente modificarlo o contattare l'autore per correggere o aggiungere funzionalità