Twig 和 Symfony2 中的自定义反式过滤器

Custom trans filter in Twig and Symfony2

出于我自己的目的,我需要覆盖标准的 Twig trans 过滤器,即我想从自定义存储中获取我的翻译。我试图在 the docs 中弄清楚。但没有关于翻译的细节。我找到了 Symfony\Bridge\Twig\Extension\TranslationExtension class 并且我认为我只需要覆盖这个 class? 提前致谢!

Symfony 的翻译组件基本上覆盖了 Twig 的默认翻译过滤器。该组件是核心 frameworkBundle 的一部分,无法禁用。

但是您可以执行相同的操作并使用您自己的 Twig 扩展重新覆盖反式过滤器。

只需按照此处所述创建一个 Twig 扩展: http://symfony.com/doc/current/cookbook/templating/twig_extension.html

如果添加翻译过滤器,它将覆盖翻译组件的代码。

只是为了扩展上面@Webberig 的回答,在 Symphony v3.0.4 和 Twig v1.24.0 中,您定义服务的方式似乎很重要。

我想为默认的 trans() 过滤器添加域回退功能,但不知道如何覆盖默认过滤器。我终于成功了:

在app/config/services.yml

# This is important!! Use this exact service ID (twig.extension.trans)
twig.extension.trans:
  class: AppBundle\Twig\AppTranslationExtension
  public: false
  arguments: ['@translator']
  tags:
    - { name: twig.extension }

这基本上就是为我做的:在我的配置中使用完全相同的服务 ID。

对于其余部分,我只是重写了 trans 过滤器方法。这是给感兴趣的人的:

namespace AppBundle\Twig;

use Symfony\Bridge\Twig\Extension\TranslationExtension;
use Symfony\Component\Translation\TranslatorInterface;

class AppTranslationExtension extends TranslationExtension
{
    public function __construct(
            TranslatorInterface $translator, 
            \Twig_NodeVisitorInterface $translationNodeVisitor = null)
    {
        parent::__construct($translator, $translationNodeVisitor);
    }

    /**
     * {@inheritdoc}
     */
    public function getFilters()
    {
        return array(
            new \Twig_SimpleFilter('trans', array($this, 'trans')),
        );
    }

    public function trans($id, array $parameters = array(), $domain = null, $locale = null)
    {
        if (null === $locale) {
            $locale = $this->getTranslator()->getLocale();
        }

        if (null === $domain) {
            $domain = 'messages';
        }

        if ('messages' !== $domain 
        && false === $this->translationExists($id, $domain, $locale)) {
            $domain = 'messages';
        }

        return $this->getTranslator()->trans($id, $parameters, $domain, $locale);
    }

    protected function translationExists($id, $domain, $locale)
    {
        return $this->getTranslator()->getCatalogue($locale)->has((string) $id, $domain);
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'app_translator';
    }
}

在@Webberig 之后详细说明,您可以定义自己的翻译扩展而不覆盖原始扩展(IMO 不好,因为您必须至少维护构造函数签名)并且只需使用原始扩展作为 inner 服务并访问原始的 trans() 成员函数,根据定义应该总是 public...

# config/services.yaml
...
    App\Twig\TranslationExtension:
        arguments: ['@twig.extension.trans']
        tags:
            - { name: twig.extension, priority: 100 }
...
// src\Twig\TranslationExtension.php
namespace App\Twig;

use Symfony\Bridge\Twig\Extension\TranslationExtension as BaseTranslationExtension;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;

class TranslationExtension extends AbstractExtension
{
    /**
     * @var BaseTranslationExtension
     */
    protected $inner;
    public function __construct(BaseTranslationExtension $inner)
    {
        $this->inner = $inner;
    }

    public function getFilters()
    {
        return [
            new TwigFilter('trans', [$this, 'trans']),
        ];
    }

    public function trans($message, array $arguments = [], $domain = null, $locale = null, $count = null)
    {
        // do ugly stuff

        return $this->inner->trans($message, $arguments, $domain, $locale, $count);
    }
}

(用于SF4.2)