Symfony 2. Мультиязычность контента

Недавно передо мной стояла задача сделать мультиязычность контента у сайта, написанного с использованием фреймворка 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

Спасибо за внимание.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*

code