Twig和Symfony2中的自定义传输过滤器

时间:2015-01-23 10:24:41

标签: php symfony twig translation twig-extension

出于我的特殊目的,我需要覆盖标准的Twig trans过滤器,例如:我想从自定义存储中获取翻译。所以我不知道自己需要做什么。我试着在docs中找出答案。但是没有关于翻译的描述。我发现Symfony\Bridge\Twig\Extension\TranslationExtension课程,我想我可能只需要覆盖这门课程?谢谢!

3 个答案:

答案 0 :(得分:2)

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

但是,您可以使用自己的Twig扩展名重新覆盖trans过滤器。

只需创建一个Twig扩展,如下所述: http://symfony.com/doc/current/cookbook/templating/twig_extension.html

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

答案 1 :(得分:2)

为了扩展@ 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。

其余的我刚刚覆盖了反式滤波器方法。这是有兴趣的人:

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';
    }
}

答案 2 :(得分:0)

要在@Webberig之后进行详细说明,您可以定义自己的翻译扩展名,而不必覆盖原始扩展名(由于IMO不好,因为您必须至少保留构造函数签名),并且只需将原始扩展名用作 inner 即可。 strong>服务并根据定义始终访问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)