Custom trans filter in Twig and Symfony2
Asked Answered
I

3

7

I need to override the standard Twig trans filter for my own purposes, i.e I want to get my translations from a custom storage. I tried to figure it out in the docs. But there is no details about translations. I found the Symfony\Bridge\Twig\Extension\TranslationExtension class and I think that I only need to override this class? Thanks in advance!

Inherited answered 23/1, 2015 at 10:24 Comment(5)
It would be best to create a custom loader rather than overriding the trans filter. There is an example of making on for loading from the DB here - blog.elendev.com/development/php/symfony/… - which you may be able to expand on to fit your purposes.Aminta
Take a look at symfony.com/doc/current/components/translation/…. You could use the existing loaders and add resources from your custom storage.Physiology
@Holger, yes, I already create my custom loader, but I dont know how use only my loader, emmm, first I load all translations from using basic loaders, then I place it in my custom storage, and I want that trans will search for translation in my storage.Inherited
I would avoid loading different resources into one translation domain. Been there, seen this... Solved it by creating a new message domain and an overridden translator class, that switched to the default domain if no translation was found in first case.Physiology
You should post your code as an answer so people with the same problem will have a solutionProse
D
2

The Translations component of Symfony basically overrides Twig's default trans filter. The component is part of the core frameworkBundle and can't be disabled.

You can however do the same and re-override the trans filter with your own Twig extension.

Just create a Twig extension as described here: http://symfony.com/doc/current/cookbook/templating/twig_extension.html

If you add a trans filter, it will override the Translation component's code.

Dryden answered 15/4, 2015 at 14:36 Comment(0)
A
4

Just to expand on @Webberig's answer above, in Symphony v3.0.4 and Twig v1.24.0, the way you define your service seems important.

I wanted to add a domain fallback capability to the default trans() filter but couldn't figure out how to override the default filter. I finally succeeded like so:

In 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 }

And that's what basically did it for me: using the same exact service ID in my config.

For the rest I just overrided the trans filter method. Here it is for those interested:

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';
    }
}
Adria answered 29/4, 2016 at 11:0 Comment(1)
I have edited the post for Symfony 4.4 yaml config.Coastland
D
2

The Translations component of Symfony basically overrides Twig's default trans filter. The component is part of the core frameworkBundle and can't be disabled.

You can however do the same and re-override the trans filter with your own Twig extension.

Just create a Twig extension as described here: http://symfony.com/doc/current/cookbook/templating/twig_extension.html

If you add a trans filter, it will override the Translation component's code.

Dryden answered 15/4, 2015 at 14:36 Comment(0)
B
0

To elaborate after @Webberig, you can define your own translation extension without overriding the original one (wich IMO is bad because you have to maintain at least the constructor signature) and just use the original extension as inner service and access the original trans() member function wich should be always public by definition...

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

(used against SF4.2)

Brocade answered 13/2, 2019 at 9:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.