如何正确管理数据库中的 Symfony 翻译

问题描述

我实际上正在处理一个 Symfony 4.4 项目,我需要能够从管理界面更新 Twig 模板翻译。

这是我第一次尝试实现基于数据库的翻译系统,所以我遵循了这个教程:https://medium.com/@andrew72ru/store-translation-messages-in-database-in-symfony-3f12e579df74

此时,我做了一个简单的类,它从我的数据库中加载一个 MessageCatalogue

<?PHP

namespace App\Service;

use App\Entity\Translation;
use App\Repository\TranslationRepository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ObjectRepository;
use Symfony\Component\Translation\Loader\LoaderInterface;
use Symfony\Component\Translation\MessageCatalogue;

class DatabaseTranslationManager implements LoaderInterface
{    
    private EntityManagerInterface $entityManager;

    public function __construct(EntityManagerInterface $doctrine)
    {
        $this->entityManager = $doctrine;
    }

    /**
     * @param mixed  $resource
     * @param string $locale
     * @param string $domain
     */
    public function load($resource,$locale,$domain = 'messages'): MessageCatalogue
    {
        $translationRepository = $this->getRepository();
        if (false === $translationRepository instanceof TranslationRepository) {
            return new MessageCatalogue($locale);
        }
        $messages = $translationRepository->findByDomainAndLocale($domain,$locale);
        $values = array_map(
            static function (Translation $entity) {
                return $entity->getTranslation();
            },$messages
        );

        return new MessageCatalogue(
            $locale,[
                $domain => $values,]
        );
    }

    /**
     * @return ObjectRepository<Translation>
     */
    public function getRepository(): ObjectRepository
    {
        return $this->entityManager->getRepository(Translation::class);
    }
}

在我的服务中注册内容

translation.loader.db:
    class: App\Service\DatabaseTranslationManager
    arguments:
        - '@doctrine.orm.entity_manager'
    tags:
        - { name: translation.loader,alias: db }

关联的 Translation 实体非常简单:

<?PHP

namespace App\Entity;

use App\Repository\TranslationRepository;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=TranslationRepository::class)
 */
class Translation
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private ?int $id = null;

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

    /**
     * @ORM\Column(type="string",length=2)
     */
    private string $locale;

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

    /**
     * @ORM\Column(type="text")
     */
    private string $translation;

    public function __construct(string $domain,string $locale,string $key,string $translation)
    {
        $this->domain = $domain;
        $this->locale = $locale;
        $this->key = $key;
        $this->translation = $translation;
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getDomain(): string
    {
        return $this->domain;
    }

    public function setDomain(string $domain): self
    {
        $this->domain = $domain;

        return $this;
    }

    public function getLocale(): string
    {
        return $this->locale;
    }

    public function setLocale(string $locale): self
    {
        $this->locale = $locale;

        return $this;
    }

    public function getKey(): string
    {
        return $this->key;
    }

    public function setKey(string $key): self
    {
        $this->key = $key;

        return $this;
    }

    public function getTranslation(): string
    {
        return $this->translation;
    }

    public function setTranslation(string $translation): self
    {
        $this->translation = $translation;

        return $this;
    }
}

目前效果很好,但我仍然面临一些问题:

  • 我需要创建空的 <domain>.<locale>.db 文件,以便触发自定义翻译加载器,这可以但并不理想
  • 每次更改数据库中的翻译时,我似乎都需要清除 Symfony 缓存。这是一个问题,因为我需要无法访问控制台的管理员用户随时更新翻译
  • 每次重置数据库时,我都会丢失所有翻译。如果数据库中不存在翻译,对我来说最好的选择是加载我的 <domain>.<locale>.yaml 文件作为后备。

由于目前我找不到更好的解决方案,我正在寻找有关如何实现此类翻译系统的建议。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)