Replacing the Translator service in Symfony 3

后端 未结 3 1361
长发绾君心
长发绾君心 2020-12-11 19:58

In my Symfony 2.8 project I have an extension that adds some extra logic to the trans method:

parameters:
    translator.class: MyBundle\\Tw         


        
相关标签:
3条回答
  • 2020-12-11 20:29

    Here is full working example how to decorate translator service in symfony 3 and replace parameter in all translated strings.

    Decorate service in config:

    # 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
    

    Create new translator that reuses original translator and adds parameters defined in service config. The only new code is updateParameters() method and call to it:

    # 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);
        }
    }
    

    Now every time you translate message %app_config% will replaced with parameter from config (e.g. parameters.yml) and %PRETTY_ERROR% will be replace with static string. If needed it is possible to override same parameters when calling trans:

    {{ 'layout.title.home'|trans({'%app_name%': 'Real App No. 1'}) }}

    Read about service decoration here

    0 讨论(0)
  • 2020-12-11 20:32

    @Aurelijus Rozenas:

    add this in your Translator:

    public function __call($method, $args)
    {
        return \call_user_func_array(array($this->translator, $method), $args);
    }
    
    0 讨论(0)
  • 2020-12-11 20:45

    Instead of extending, it would be better to decorate the translator service. Right now you overriding the class name, which will also override other bundles that want to decorate the service. And I see you made it an extension because of Twig, the original Twig {{ trans() }} filter will use the decorated service too.

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

    See documentation about decorating here: http://symfony.com/doc/current/service_container/service_decoration.html

    0 讨论(0)
提交回复
热议问题