Мы уже рассматривали вопрос локализации данных бизнес-модели с использованием внешнего хранилища, но это решение имеет один серьезный недостаток - оно исключает возможность применения 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.