With Translatable you can translate the fields you like in your Doctrine Entity. Check out other Doctrine Extensions
- Official Doctrine Extensions installation guide here.
- Official Doctrine Translatable documentation over here.
composer.json
{
"require": {
"php": ">=5.3.2",
"symfony/symfony": "2.3.*",
"doctrine/orm": "~2.2,>=2.2.3",
"doctrine/doctrine-bundle": "~1.2",
"gedmo/doctrine-extensions": "dev-master",
}
}
app/config/parameters.yml
parameters:
locale: nl
app/config/config.yml
imports:
# ...
- { resource: doctrine_extensions.yml }
doctrine:
dbal:
# your dbal config here
orm:
auto_generate_proxy_classes: %kernel.debug%
auto_mapping: true
# only these lines are added additionally
mappings:
translatable:
type: annotation
alias: Gedmo
prefix: Gedmo\Translatable\Entity
# make sure vendor library location is correct
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"
app/config/doctrine_extensions.yml
# services to handle doctrine extensions
services:
# KernelRequest listener
extension.listener:
class: Acme\DemoBundle\Listener\DoctrineExtensionListener
calls:
- [ setContainer, [ @service_container ] ]
tags:
# translatable sets locale after router processing
- { name: kernel.event_listener, event: kernel.request, method: onLateKernelRequest, priority: -10 }
# loggable hooks user username if one is in security context
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
gedmo.listener.translatable:
class: Gedmo\Translatable\TranslatableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ @annotation_reader ] ]
- [ setDefaultLocale, [ %locale% ] ]
- [ setTranslationFallback, [ false ] ]
# set - [ setTranslationFallback, [ true ] ] if you want fallback functionality
src/Acme/DemoBundle/Listener/DoctrineExtensionListener.php
We must initialize translatable on kernel.request.
<?php
// file: src/Acme/DemoBundle/Listener/DoctrineExtensionListener.php
namespace Acme\DemoBundle\Listener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class DoctrineExtensionListener implements ContainerAwareInterface
{
/**
* @var ContainerInterface
*/
protected $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
public function onLateKernelRequest(GetResponseEvent $event)
{
$translatable = $this->container->get('gedmo.listener.translatable');
$translatable->setTranslatableLocale($event->getRequest()->getLocale());
}
public function onKernelRequest(GetResponseEvent $event)
{
$securityContext = $this->container->get('security.context', ContainerInterface::NULL_ON_INVALID_REFERENCE);
if (null !== $securityContext && null !== $securityContext->getToken() && $securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
$loggable = $this->container->get('gedmo.listener.loggable');
$loggable->setUsername($securityContext->getToken()->getUsername());
}
}
}
Updating database schema
# you can check the entities
php app/console doctrine:mapping:info
# Updating database schema: this will create the ```ext_translations``` table
php app/console doctrine:schema:create
Article Doctrine Entity
<?php
//filename: src/Backend/Modules/Blog/Entity/Article;
namespace Backend\Modules\Blog\Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Translatable\Translatable;
/**
* @ORM\Table(name="articles")
* @ORM\Entity
*/
class Article implements Translatable
{
/** @ORM\Id @ORM\GeneratedValue @ORM\Column(type="integer") */
private $id;
/**
* @Gedmo\Translatable
* @ORM\Column(name="title", type="string", length=128)
*/
private $title;
/**
* @Gedmo\Translatable
* @ORM\Column(name="content", type="text")
*/
private $content;
/**
* @Gedmo\Locale
* Used locale to override Translation listener`s locale
* this is not a mapped field of entity metadata, just a simple property
*/
private $locale;
public function getId()
{
return $this->id;
}
public function setTitle($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
public function setContent($content)
{
$this->content = $content;
}
public function getContent()
{
return $this->content;
}
public function setTranslatableLocale($locale)
{
$this->locale = $locale;
}
}
Insert Article with default language
$em = $this->get('doctrine.orm.entity_manager');
// will insert article in locale (= nl)
$article = new Backend\Modules\Blog\Entity\Article;
$article->setTitle('my title in nl');
$article->setContent('my content in nl');
$em->persist($article);
$em->flush();
Insert a translation for this Article
$em = $this->get('doctrine.orm.entity_manager');
// first load the article
$article = $em->find('Backend\Modules\Blog\Entity\Article', 1 /*article id*/);
$article->setTitle('my title in de');
$article->setContent('my content in de');
// change locale
$article->setTranslatableLocale('de_de');
$em->persist($article);
$em->flush();
Inserting multiple translations
$em = $this->get('doctrine.orm.entity_manager');
// persisting multiple translations, assume default locale is EN
$repository = $em->getRepository('Gedmo\\Translatable\\Entity\\Translation');
// it works for ODM also
$article = new Article();
$article->setTitle('My article nl');
$article->setContent('content nl');
$repository
->translate($article, 'title', 'en', 'my article en')
->translate($article, 'content', 'en', 'content en')
->translate($article, 'title', 'de', 'my article de')
->translate($article, 'content', 'de', 'content de')
->translate($article, 'title', 'ru', 'my article ru')
->translate($article, 'content', 'ru', 'content ru')
;
$em->persist($article);
$em->flush();
Database table articles
Database table ext_translations
Updating same article also having one new translation
$em = $this->get('doctrine.orm.entity_manager');
$repo
->translate($article, 'title', 'lt', 'title lt')
->translate($article, 'content', 'lt', 'content lt')
->translate($article, 'title', 'ru', 'title ru change')
->translate($article, 'content', 'ru', 'content ru change')
->translate($article, 'title', 'en', 'title en (default locale) update')
->translate($article, 'content', 'en', 'content en (default locale) update')
;
$em->flush();
Get translations
$em = $this->get('doctrine.orm.entity_manager');
// reload in different language
$article = $em->find(BackendBlogModel::ENTITY_CLASS, 1 /*article id for the item you want all translations for*/);
if (empty($article)) {
throw new \Exception('Article id not exists');
}
$article->setTranslatableLocale('en_us');
$em->refresh($article);
$article = $em->find(BackendBlogModel::ENTITY_CLASS, 1 /*article id for the item you want all translations for*/);
$repository = $em->getRepository('Gedmo\Translatable\Entity\Translation');
$translations = $repository->findTranslations($article);
More examples can be found in official documentation).