在Symfony 3中替换翻译器服务

6
在我的Symfony 2.8项目中,我有一个扩展,它向trans方法添加了一些额外的逻辑:
parameters:
    translator.class: MyBundle\Twig\TranslationExtension

这个类看起来像这样:

namespace MyBundle\Twig\TranslationExtension;

use Symfony\Bundle\FrameworkBundle\Translation\Translator as BaseTranslator;

class TranslationExtension extends BaseTranslator
{
    private $currentLocale;

    public function trans($id, array $parameters = array(), $domain = null, $locale = null)
    {
            $translation = parent::trans($id, $parameters, $domain, $locale);

            // Some extra logic here

            return $translation;
    }

    public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
    {
        return parent::transChoice($id, $number, $parameters, $domain, $locale);
    }
}

现在,我正在迁移到Symfony 3,其中那些类参数已被弃用,但是我如何通过覆盖translator服务来实现这一点呢?

3个回答

10

不要进行扩展,最好是对 translator 服务进行装饰。现在你正在覆盖类名,这也将覆盖其他想要装饰该服务的捆绑包。我知道你之所以将其作为扩展添加是因为Twig,但原始的Twig {{ trans() }} 过滤器也将使用已装饰的服务。

services:
  app.decorating_translator:
    class:     AppBundle\DecoratingTranslator
    decorates: translator
    arguments: ['@app.decorating_translator.inner'] # original translator
    public:    false

查看这里有关装饰的文档:http://symfony.com/doc/current/service_container/service_decoration.html


9
这是一个完整的工作示例,展示如何在Symfony 3中装饰翻译器服务并替换所有已翻译字符串中的参数。
在配置文件中装饰服务:
# app/config/services.yml
app.decorating_translator:
    class:     AppBundle\Translation\Translator
    decorates: translator
    arguments:
        - '@app.decorating_translator.inner'
        # passing custom parameters
        - {'%%app_name%%': '%app_name%', '%%PRETTY_ERROR%%': 'This is not nice:'}
    public:    false

创建一个新的翻译器,它可以重用原始翻译器并添加在服务配置中定义的参数。唯一的新代码是 updateParameters() 方法及其调用:
# AppBundle/Translation/Translator.php
namespace AppBundle\Translation;

use Symfony\Component\Translation\TranslatorBagInterface;
use Symfony\Component\Translation\TranslatorInterface;

class Translator implements TranslatorInterface, TranslatorBagInterface
{
    /** @var TranslatorBagInterface|TranslatorInterface */
    protected $translator;
    /** @var array */
    private $parameters;

    /**
     * @param TranslatorInterface|TranslatorBagInterface $translator
     * @param array                                      $parameters
     */
    public function __construct($translator, $parameters)
    {
        $this->translator = $translator;
        $this->parameters = $parameters;
    }

    /**
     * @param string $id
     * @param array  $parameters
     * @param null   $domain
     * @param null   $locale
     *
     * @return string
     */
    public function trans($id, array $parameters = [], $domain = null, $locale = null)
    {
        $parameters = $this->updateParameters($parameters);

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

    /**
     * @param string $id
     * @param int    $number
     * @param array  $parameters
     * @param null   $domain
     * @param null   $locale
     *
     * @return string
     */
    public function transChoice($id, $number, array $parameters = [], $domain = null, $locale = null)
    {
        $parameters = $this->updateParameters($parameters);

        return $this->translator->transChoice($id, $number, $parameters, $domain, $locale);
    }

    /**
     * @param string $locale
     */
    public function setLocale($locale)
    {
        $this->translator->setLocale($locale);
    }

    /**
     * @return string
     */
    public function getLocale()
    {
        return $this->translator->getLocale();
    }

    /**
     * @param string|null $locale
     *
     * @return \Symfony\Component\Translation\MessageCatalogueInterface
     */
    public function getCatalogue($locale = null)
    {
        return $this->translator->getCatalogue($locale);
    }

    /**
     * @param array $parameters
     *
     * @return array
     */
    protected function updateParameters($parameters)
    {
        return array_merge($this->parameters, $parameters);
    }
}

现在每次你翻译消息%app_config%时,都会用配置文件中的参数(例如parameters.yml)替换它,并且%PRETTY_ERROR%将被替换为静态字符串。 如果需要,在调用trans时可以覆盖相同的参数:

{{ 'layout.title.home'|trans({'%app_name%': '真实应用程序No. 1'}) }}

在这里阅读有关服务装饰的信息here


0

@Aurelijus Rozenas:

在你的翻译器中添加这个:

public function __call($method, $args)
{
    return \call_user_func_array(array($this->translator, $method), $args);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接