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

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
Copy link
Collaborator

garak commented Aug 19, 2019

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

@lbraconnier2
Copy link
Author

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
Copy link
Collaborator

garak 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)

@lbraconnier2
Copy link
Author

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
Development

No branches or pull requests

2 participants