This version of the bundle is in sync with Symfony master branch
- Download PUGXI18nBundle
- Enable the Bundle
- Entities
- Repository
- Form
- Customize the behaviour for default translation and translation not found
Using composer
Add the following lines in your composer.json:
{
"require": {
"pugx/i18n-bundle": "^4.2@dev"
}
}
Now, run the composer to download the bundle:
$ composer update pugx/i18n-bundle
Enable the bundle in the kernel:
<?php
// app/AppKernel.php
public function registerBundles()
{
$bundles = array(
// ...
new PUGX\I18nBundle\PUGXI18nBundle(),
);
}
<?php
namespace Acme\MyBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
class Article
{
/**
* @ORM\OneToMany(targetEntity="ArticleI18n", mappedBy="translatable", cascade={"persist"})
*/
protected $translations;
public function __construct()
{
$this->translations = new ArrayCollection();
}
}
<?php
namespace Acme\MyBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
class ArticleI18n
{
/**
*
* @ORM\Column(name="locale", type="string", length=128)
*/
private $locale;
/**
* @ORM\ManyToOne(targetEntity="Article", inversedBy="translations")
* @ORM\JoinColumn(name="article_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $translatable;
/**
*
* @ORM\Column(name="name", type="string", length=128)
*/
private $name;
}
Then run doctrine:generate:entities and remove the generated method addTranslation (for Article in this example). Now you can implements the correct interfaces.
<?php
use PUGX\I18nBundle\Model\TranslatableWrapper;
class Article extends TranslatableWrapper
{
}
TranslatableWrapper extends Translatable (that implements some methods of TranslatableInterface) and adds a magic method to wrap the methods of TranslatingInterface entity.
<?php
use PUGX\I18nBundle\Model\TranslatingInterface;
use PUGX\I18nBundle\Model\TranslatableInterface;
class ArtcileI18n implements TranslatingInterface
{
}
Remember to modify the signature for ArticleI18n::setTranslatable
If you want "kill the magic", you can extend directly PUGX\I18nBundle\Model\Translatable and create the needed wrapper methods by yourself.
<?php
namespace Acme\MyBundle\Repository;
use Doctrine\ORM\EntityRepository;
class ArticleRepository extends EntityRepository
{
public function getArticleTranslatedQuery()
{
$q = $this->createQueryBuilder('a')
->select(array('a', 'at'))
->leftJoin('a.translations', 'at');
return $q;
}
}
A possible form implementation
<?php
namespace Acme\MyBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class ArtcileI18nFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('locale', 'hidden');
$builder->add('name');
}
public function setDefaultOptions(array $options)
{
return array(
'data_class' => 'Acme\MyBundle\Entity\ArtcileI18n',
);
}
public function getName()
{
return 'translation';
}
}
namespace Acme\MyBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class ArticleType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('translations', 'collection', array(
'type' => new ArtcileI18nFormType(),
'allow_add' => true,
'by_reference' => false,
));
}
}
[Allowing "new" tags with the "prototype"] (http://symfony.com/doc/current/cookbook/form/form_collections.html#allowing-new-tags-with-the-prototype)
If you want use as default translation, the first found translation even if is not a translation for current locale neither for default locale
protected function acceptFirstTransaltionAsDefault()
{
return true;
}
If you want a translation, only if was found one for the current locale
protected function acceptDefaultLocaleTransaltionAsDefault()
{
return false;
}
If you want manage by yourself the behaviour in case of translation not found
protected function handleTranslationNotFound()
{
//your logic
}
for example
protected function handleTranslationNotFound()
{
$class = get_class($this) . 'Translation';
if (class_exists($class)) {
$this->translation = new $class;
} else {
$this->translation = null;
}
}