用nelmio / alice和gedmo / doctrine-extensions创建Fixture可翻译

时间:2015-03-20 14:41:31

标签: symfony doctrine-orm

我使用Translatable behaviour of Atlantic18/DoctrineExtensions来翻译我的实体的某些字段。

有没有办法在yml中使用nelmo/alice创建数据夹具并在我的实体中设置多个翻译?

例如,我有:     

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Translatable\Translatable;

/**
 * Lang
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class Lang implements Translatable
{
    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     * @Gedmo\Translatable
     */
    private $name;

    /...
}

在我的数据夹具中:      

use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\Persistence\ObjectManager;
use AppBundle\Entity\Lang;

class LangData extends AbstractFixture implements FixtureInterface
{
    /**
     * {@inheritDoc}
     */
    public function load(ObjectManager $manager)
    {

        $langs = array(
            array('French', 'Français'),
            array('English', 'Anglais')
        );
        $repo = $manager->getRepository('GedmoTranslatable:Translation');

        foreach ($langs as $aLang) {
            $oLang = new Lang();
            $oLang->setName($aLang[0]);

            $repo->translate($oLang, 'name', 'fr', $aLang[1]);
            $manager->persist($oLang);
        }
        $manager->flush();
    }
}

我想做类似的事情:

AppBundle\Entity\Lang:
    fr:
        name: French
        name_fr: Français
    en:
        name: English
        name_fr: Anglais

或者可能在多个文件中。

由于

3 个答案:

答案 0 :(得分:0)

您可以创建一个TranslatableProcessor服务,该服务实现Nelmio \ Alice \ ProcessorInterface并转换对象属性。

https://gist.github.com/istvankis/0010cf0e318258146d4f203007aaf1e2

对于语言翻译,我建议使用Symfony Intl组件

http://symfony.com/doc/current/components/intl.html#language-and-script-names

答案 1 :(得分:0)

最后,我找到了一个真正简单的解决方案:

# src/DataFixtures/ORM/fixtures.yaml
App\Entity\Gender:
  gender:
    locale: 'en'
    name: 'Female'

如果您的实体具有locale属性,则此方法有效(更多详细信息在Gedmo文档中)。您所要做的就是为此属性添加一个setter:

# src/Entity/Gender.php
<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Translatable\Translatable;

/**
 * @ORM\Entity(repositoryClass="App\Repository\GenderRepository")
 */
class Gender implements Translatable
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @Gedmo\Translatable
     * @ORM\Column(type="string", length=255)
     */
    private $name;

    /**
     * @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(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    //
    //     This one is to satisfy Gedmo :)
    //
    public function setTranslatableLocale($locale): self
    {
        $this->locale = $locale;

        return $this;
    }

    //
    //     This one is to satisfy Alice :)
    //
    public function setLocale(string $name): self
    {
        $this->locale = $name;

        return $this;
    }
}

答案 2 :(得分:0)

灯具配置:

App\Entity\Product:
  t_shirt:
    translatable_locale: 'en|de'
    name: 'My cool T-shirt|Mein cooles T-Shirt'

src/DataFixtures/TranslationsProcessor.php中的处理器:

<?php

namespace App\DataFixtures;

use Doctrine\Common\Annotations\Reader;
use Doctrine\ORM\EntityManagerInterface;
use Fidry\AliceDataFixtures\ProcessorInterface;
use Gedmo\Mapping\Annotation\Translatable;

class TranslationsProcessor implements ProcessorInterface
{
    private $reader;
    private $em;

    public function __construct(EntityManagerInterface $em, Reader $reader)
    {
        $this->reader = $reader;
        $this->em = $em;
    }

    public function preProcess(string $id, $object): void
    {
    }

    public function postProcess(string $id, $object): void
    {
        $class = new \ReflectionClass(get_class($object));

        if (null === $locales = $this->getLocales($class, $object)) {
            return;
        }

        foreach ($class->getProperties() as $property) {
            foreach ($this->reader->getPropertyAnnotations($property) as $annotation) {
                if ($annotation instanceof Translatable) {
                    $property->setAccessible(true);
                    $translations = explode('|', $property->getValue($object));
                    if (count($locales) !== count($translations)) {
                        throw new \Exception(sprintf('The number of translations in property "%s" of "%s" does not match the number of translatable_locale.', $property->getName(), $class->getName()));
                    }
                    foreach ($locales as $i => $locale) {
                        $property->setValue($object, $translations[$i]);
                        $object->setTranslatableLocale($locale);
                        $this->em->persist($object);
                        $this->em->flush();
                    }
                }
            }
        }
    }

    private function getLocales(\ReflectionClass $class, $object): ?array
    {
        try {
            $property = $class->getProperty('locale');
        } catch (\ReflectionException $e) {
            return null;
        }
        $property->setAccessible(true);
        $locales = $property->getValue($object);
        return explode('|', $locales);
    }
}