Мы уже рассматривали вопрос локализации данных бизнес-модели с использованием внешнего хранилища, но это решение имеет один серьезный недостаток - оно исключает возможность применения SQL для фильтрации и сортировки сущностей. Это вызвано тем, что реляционная база данных не имеет доступа к хранилищу переводов бизнес-модели, но решить эту проблему можно вынеся данные локализации в базу данных.
Базовая модель
В данной модели поле content
выносится в отдельную сущность, представляющую различные переводы этого поля. Сама же сущность Entity
будет хранить коллекцию EntityTranslate
и предоставлять значение поля content
в зависимости от текущей локали.
<?php
class Entity{
private $id;
// Все экземпляры класса EntityTranslate данной сущности в виде массива, проиндексированного локалью.
private $contentTranslations;
...
public function getContent($locale){
return $this->contentTranslations[$locale]->getContent();
}
}
class EntityTranslate{
private $id;
private $content;
private $locale;
...
public function getContent(){
return $this->content;
}
}
Помните, что класс
EntityTranslate
может хранить все поля, нуждающиеся в переводе для сущности. Другими словами не следует создавать для каждого переводимого поля по отдельному классу перевода.
База данных, в данном случае, должна быть дополнена таблицей entity_translate
, которая будет включать переводы поля content
. Связь между классами Entity
и EntityTranslate
будет иметь множественную кратность с обоих концов, что потребует так же дополнительной таблицы связей entity_entity_translate_link
.
Реализации
Одной из реализаций описанной модели является пакет Atlantic18/DoctrineExtensions, включающий механизм локализации сущностей, основанных на ORM Doctrine.