Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Synfony 4.3 translator decorates failure in prod mode, work great in dev #572

Open
lbraconnier2 opened this issue Aug 19, 2019 · 4 comments

Comments

@lbraconnier2
Copy link

commented Aug 19, 2019

For our stuff, we need to decorate the symfony translator.
it works very well in "dev" mode, but when symfony app is configured in "prod" mode
we have this message :

_Argument 2 passed to Knp\Bundle\PaginatorBundle\Helper\Processor::_construct() must implement interface Symfony\Component\Translation\TranslatorInterface, instance of App\Services\CustomTranslator given

below the service.yaml configuration
image

and the decorator code :

<?php
namespace App\Services;

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

/**
 * Class Translator
 * To handle translation identifier formated like that : '|CodeJournal|symfony.great'
 * Pipe at the beginning to avoid searching all string for the 1% of translation outside 'messages' domain.
 *
 * How to use ?
 * Add it in service.yml :
 *    app_decorating_translator:
 *        class:     App\Services\CustomTranslator
 *        decorates: translator
 *        arguments:
 *            - '@app_decorating_translator.inner'
 *        public: false
 */
class CustomTranslator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface
{
    /** @var TranslatorBagInterface|TranslatorInterface */
    protected $translator;

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

    /**
     * Custom function
     * use of references parameters to limit variables usages.
     *
     * @param $id
     * @param $domain
     */
    private function applyCustomPipe(&$id, &$domain)
    {
        // if pipe at the start of the received translation identifier
        if (is_string($id) && substr($id, 0, 1) === '|') {
            // search for the second pipe
            $pos = strpos($id, '|', 1); // faster than regex
            if ($pos > 1) {
                $domain = substr($id, 1, $pos - 1);
                $id = substr($id, $pos + 1); // real identifier without |domain|
            }
        }
    }

    /**
     * Override Symfony function trans(), used for simple translation.
     *
     * @param string $id
     * @param array  $parameters
     * @param null   $domain
     * @param null   $locale
     *
     * @return string
     */
    public function trans($id, array $parameters = [], $domain = null, $locale = null)
    {
        $this->applyCustomPipe($id, $domain);

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

    /**
     * Override Symfony function transChoice(), used for pluralized translation.
     *
     * @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)
    {
        $this->applyCustomPipe($id, $domain);

        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);
    }
}
@garak

This comment has been minimized.

Copy link
Collaborator

commented Aug 19, 2019

I see your service is not implementing Symfony\Component\Translation\TranslatorInterface

@lbraconnier2

This comment has been minimized.

Copy link
Author

commented Aug 20, 2019

That's right, we implement, Symfony\Contracts\Translation\LocaleAwareInterface and
Symfony\Contracts\Translation\TranslatorInterface because Symfony\Component\Translation\TranslatorInterface is deprecated since 4.2

@garak

This comment has been minimized.

Copy link
Collaborator

commented Aug 20, 2019

I'm afraid you need to keep the deprecated class for now.
A possible alternate solution is to write your own helper and use it instead of bundle's one.
Another possible solution is to change bundle's helper to be flexible and accept new Symfony translator (PR is welcome)

@garak garak added the improvement label Aug 20, 2019

@lbraconnier2

This comment has been minimized.

Copy link
Author

commented Aug 20, 2019

Thanks a lot, we will try this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.