Как использовать Yii с моделью многоязычной базы данных?

У меня возникла проблема с получением данных из моей базы данных, которые я создал, чтобы быть полностью многоязычными, и я надеюсь, что кто-то здесь может мне помочь.

Ive разделил все мои таблицы на 2 части; "универсальная" таблица (не содержит текст, который необходимо перевести), и таблицу, содержащую все поля, которые необходимо перевести с их переводами.

Примеры таблиц:

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'

Мой вопрос заключается в том, как я могу автоматически получить эти переводы (с исходным языком, как в этом запросе), прикрепленным к моей модели в Yii, когда Im ищет объекты base_material? (Это только 1 таблица примеров, но почти все мои таблицы (20+) построены таким образом, поэтому, если возможно, мне будет нужно что-то гибкое)

Примером существующей системы, использующей то, что мне нужно, является Propel: http://propel.posterous.com/propel-gets-i18n-behavior-and-why-it-matters

Любые идеи, как это сделать? Ive проверил существующие расширения Yii в отношении многоязычных сайтов (например, Многоязычная активная запись), но все они используют другой дизайн базы данных (общая информация + откат язык в главной таблице, переводы в таблице i18n), и я не уверен, как изменить эти расширения для использования моей модели БД.

Если кто-то знает способ изменить существующее расширение, чтобы он мог использовать мою схему БД, тогда это было бы абсолютно блестящим и, вероятно, лучшим способом сделать это.

Изменить: я добавил щедрость, потому что я все еще не могу найти что-либо о том, как заставить Propel работать с Yii (существует расширение для Doctrine, но Doctrine не поддерживает такую ​​модель DB с переводами либо), а также больше информации о том, как справиться с этим, используя существующее расширение Yii или с областями.

Изменить: просмотрено 98 раз, но только 3 upvotes и 1 комментарий. Я не могу не чувствовать, что я делаю что-то не так, будь то в моем вопросе или проекте приложения/базы данных; либо это, либо моя проблема просто уникальна (что меня удивило бы, так как я не думаю, что мой многоязычный дизайн базы данных абсурден;-). Итак, если кто-нибудь знает о более широком решении для многоязычных сайтов с Yii и/или Propel (помимо текущих расширений, которые мне действительно не нравятся из-за дублирования текстовых полей) или что-то подобное, сообщите мне также.

Спасибо заранее!

Ответ 1

Я также ищу универсальное решение для внедрения i18n в модели Yii. Недавно я выбрал очень похожую схему базы данных для такого проекта, как вы. Единственное различие заключается в том, что я не использую отдельную таблицу языков, я храню информацию о языке в таблице i18n.

Следующее решение без пользовательской инструкции SQL, но я думаю, что это может быть реализовано с параметрами отношения, в любом случае, если вы работаете с внешним ключом в своей базе данных (например, MySQL InnoDB), gii создаст отношения между вашим базовым_материалом и 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!

Ответ 2

Вы пробовали http://www.yiiframework.com/extension/i18n-columns/ (на основе http://www.yiiframework.com/extension/stranslateablebehavior/)?

Это альтернативный, более простой подход, добавляя новые поля таблицы в стиле {поле} _ {код языка}, а затем устанавливая переведенное поле в исходной модели на текущий перевод языка на afterFind.

По сути, он заставит вас работать с переводимыми полями, при этом переведенный контент будет автоматически загружен, для хорошего и плохого:). Добавление и удаление языков (= столбцы) выполняется с помощью миграции.

Ответ 3

Вы можете попытаться использовать простое многоязычное расширение CRUD. он очень прост в использовании и модификации. вам просто нужно добавить языковое поле в таблицу. просто смотрите описание здесь: http://all-of.me/yii-multilingual-crud/ он находится в альфа-состоянии, но пробовал по нескольким проектам. вы можете легко модифицировать его или связаться с автором, чтобы исправить или добавить функции.