使用Doctrine处理可翻译实体,并将翻译存储在同一行中

时间:2015-12-10 09:27:35

标签: php symfony doctrine-orm translation doctrine-extensions

我正在寻找自动翻译Symfony应用程序实体的解决方案。我坚持使用遗留数据库,其中翻译与额外字段存储在同一个表中:

id | name | name_de | name_fr
 1 | cat  | Katze   | chat
 2 | dog  | Hund    | chien

我的实体按照以下方式进行了映射:

class Animal
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     *
     * @var integer
     */
    private $id;

    /**
     * @ORM\Column(name="name", type="string", length=64, nullable=false)
     *
     * @var string
     */
    private $name;

    /**
     * @ORM\Column(name="name_de", type="string", length=64, nullable=false)
     *
     * @var string
     */
    private $nameDe;

    /**
     * @ORM\Column(name="name_fr", type="string", length=64, nullable=false)
     *
     * @var string
     */
    private $nameFr;

    /* Followed by getters and setters */
}

我已经查看了Translatable扩展名,但这与我的数据库架构不匹配。我还开始使用自定义注释挂钩到postLoad事件,但后来我被一个简单的问题所阻止,postLoad可能在实体的代理状态中被触发。

接下来我要研究一个自定义查询walker(基本上是可翻译扩展的修改方法),但我希望那里的解决方案不那么复杂。

干杯 的Matthias

1 个答案:

答案 0 :(得分:1)

这里有很多解决方案,我想我没看过其中的一半。

无论如何,到目前为止我提出的最简单且至少有点干净的解决方案是使用静态类进行翻译。这看起来像这样:

class Translation
{

    /**
     * @var string
     */
    private static $language;

    /**
     * tries to get a translated property by prepending the
     * configured language to the given entities getter
     *
     * @param object $entity
     * @param string $getter
     * @return mixed
     */
    public static function getTranslated($entity, $getter) {
        $language = self::getLanguage();
        $translatedGetter = $getter.$language;
        if(method_exists($entity, $translatedGetter)) {
            return $entity->$translatedGetter();
        } else {
            return $entity->$getter;
        }
    }

    /**
     * @return string
     */
    public static function getLanguage()
    {
        return self::$language;
    }

    /**
     * @param string $language
     */
    public static function setLanguage($language)
    {
        self::$language = ucfirst(strtolower($language));
    }

}

然后,您可以在应用程序启动时设置语言,并在您的实体中实现翻译:

/**
 * @return string
 */
public function getName()
{
    return Translation::getTranslated($this, __FUNCTION__);
}

或从外面打电话:

Translation::getTranslated($animal, "getName");

所以使用第一种方法代码:

Translation::setLanguage("DE");

// far more code

/** @var Animal[] $animals */
$animals = $entityManager->getRepository(Animal::class)->findAll();

foreach ($animals as $animal) {
    echo $animal->getName()."<br >";
}

会推出:

Katze
Hund

当然,这只是使用静态类的一种方法。