In my Symfony 2.8 project I have an extension that adds some extra logic to the trans method:
parameters:
translator.class: MyBundle\Twig\TranslationExtension
The class looks like this:
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);
}
}
Now, I'm migrating to Symfony 3, where those class parameters are deprecated, but how can I implement this by overwriting the translator service?
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With