Недавно передо мной стояла задача сделать мультиязычность контента у сайта, написанного с использованием фреймворка symfony 2. Из мануалов было ясно, что встроенная мультиязычность подходит только для перевода интерфейсов. Мне нужна возможность определения у каких полей сущностей будет перевод, а у каких не будет перевода.
Нашел библиотеку Doctrine2 Behaviors от KnpLabs. В документации есть инструкция по использованию с анотациями. Но у меня сущности описываются в yml файлах. С yml файлами, как оказалось тоже все работает, главное — правильно описать.
Установить Doctrine2 Behaviors можно следующей командой:
composer require knplabs/doctrine-behaviors:~1.1
После установки нужно подключить бандл в файле app/AppKernel.php
class AppKernel
{
function registerBundles()
{
$bundles = array(
//...
new Knp\DoctrineBehaviors\Bundle\DoctrineBehaviorsBundle(),
//...
);
//...
return $bundles;
}
}
И импортировать сервисы в файле app/config/config.yml
# app/config/config.yml
imports:
- { resource: ../../vendor/knplabs/doctrine-behaviors/config/orm-services.yml }
Установка завершена. Можно приступать к работе с библиотекой.
Создадим сущность Page. Для этого нам понадобится файл Page.yml
AppBundle\Entity\Page:
type: entity
table: Page
repositoryClass: AppBundle\Entity\Repository\PageRepository
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
title:
type: string
length: 255
text:
type: text
lifecycleCallbacks: { }
Сущность с переводом всегда называется также как и оригинальная сущность, только с суффиксом Translation. В нашем случае это будет PageTranslation. Создадим для нее файл PageTranslation.yml
AppBundle\Entity\PageTranslation:
type: entity
table: PageTranslation
fields:
title:
type: string
length: 255
nullable: true
text:
type: text
nullable: true
lifecycleCallbacks: { }
Далее выполним в консоли команду для генерации классов сущностей:
php app/console doctrine:generate:entities AppBundle
И команду для создания таблиц в базе данных:
php app/console doctrine:schema:update --force
Теперь нужно внести изменения в файлы классов. В файл Page.php добавим следующие строки:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
class Page
{
use ORMBehaviors\Translatable\Translatable;
/**
* @ORM\Column(type="string", length=255)
*/
protected $someFieldYouDoNotNeedToTranslate;
В класс PageTranslation добавим следующие строки:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
class PageTranslation
{
use ORMBehaviors\Translatable\Translation;
Теперь создание страницы с переводами на английском и французском языках будет выглядеть так:
<?php
$page = new Page();
$page->setTitle('Заголовок на русском языке');
$page->setText('Текст на русском языке');
$page->translate('en')->setTitle('Заголовок на английском языке');
$page->translate('fr')->setTitle('Заголовок на французском языке');
$page->translate('en')->setText('Текст на английском языке');
$em = $this->get('doctrine.orm.entity_manager');
$em->persist($page);
// Метод mergeNewTranslations() нужно вызывать до метода flush()
$page->mergeNewTranslations();
$em->flush();
Получение перевода осуществляется тоже через метод translate()
<?php
$id = 1;
$page = $this->getDoctrine()
->getRepository('ContentBundle:Page')
->find($id);
$title_ru = $page->getTitle();
$title_en = $page->translate('en')->getTitle();
$title_fr = $page->translate('fr')->getTitle();
Данный способ переводов проверен на версиях symfony 2.6 и symfony 2.7
Спасибо за внимание.