Заменить / украсить `translation.reader` - PullRequest
0 голосов
/ 16 октября 2018

Я заполнил ошибку, но она кажется, что я выключен: p

Я просто хочу заменить службу Symfony\Component\Translation\Reader\TranslationReader (translation.reader) своим собственным классом.На самом деле я хочу знать, как заменить любой сервис SF4, если я хочу, чтобы

translation.reader::addLoader() обычно вызывался фреймворком, но если я украшал свой собственный класс, addLoader не вызывался.

Можете ли вы сказать мне, как я могу просто отбросить заменить свой собственный сервис?

https://github.com/symfony/symfony/issues/28843

Затронутые версии Symfony : 4.1.6

Описание
Невозможно украсить translation.reader (я хочу изменить процесс загрузки файлов по умолчанию i18n)

Как воспроизвести

копировать / адаптировать Symfony\Component\Translation\Reader\TranslationReader к App\Translation\Reader\TranslationReader

Follow https://symfony.com/doc/current/service_container/service_decoration.html

Изменить services.yaml

Symfony\Component\Translation\Reader\TranslationReader: ~

App\Translation\Reader\TranslationReader:
    decorates: Symfony\Component\Translation\Reader\TranslationReader

#translation.reader: '@App\Translation\Reader\TranslationReader'

Без псевдонима:новый сервис игнорируется с псевдонимом: read() является триггером, но не addLoader()

Вот сгенерированный файл инъекции getTranslationReaderService.php:

<?php

use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
// Returns the private 'App\Translation\Reader\TranslationReader' shared autowired service.

include_once $this->targetDirs[3].'/vendor/symfony/translation/Reader/TranslationReaderInterface.php';
include_once $this->targetDirs[3].'/src/Translation/Reader/TranslationReader.php';

return $this->privates['App\Translation\Reader\TranslationReader'] = new \App\Translation\Reader\TranslationReader();

По умолчанию это выглядит так:

use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
// Returns the private 'translation.reader' shared service.

include_once $this->targetDirs[3].'/vendor/symfony/translation/Reader/TranslationReaderInterface.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Reader/TranslationReader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/LoaderInterface.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/ArrayLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/FileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/PhpFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/YamlFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/XliffFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/PoFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/MoFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/QtFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/CsvFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/IcuResFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/IcuDatFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/IniFileLoader.php';
include_once $this->targetDirs[3].'/vendor/symfony/translation/Loader/JsonFileLoader.php';

$this->privates['translation.reader'] = $instance = new \Symfony\Component\Translation\Reader\TranslationReader();

$a = ($this->privates['translation.loader.yml'] ?? $this->privates['translation.loader.yml'] = new \Symfony\Component\Translation\Loader\YamlFileLoader());
$b = ($this->privates['translation.loader.xliff'] ?? $this->privates['translation.loader.xliff'] = new \Symfony\Component\Translation\Loader\XliffFileLoader());

$instance->addLoader('php', ($this->privates['translation.loader.php'] ?? $this->privates['translation.loader.php'] = new \Symfony\Component\Translation\Loader\PhpFileLoader()));
$instance->addLoader('yaml', $a);
$instance->addLoader('yml', $a);
$instance->addLoader('xlf', $b);
$instance->addLoader('xliff', $b);
$instance->addLoader('po', ($this->privates['translation.loader.po'] ?? $this->privates['translation.loader.po'] = new \Symfony\Component\Translation\Loader\PoFileLoader()));
$instance->addLoader('mo', ($this->privates['translation.loader.mo'] ?? $this->privates['translation.loader.mo'] = new \Symfony\Component\Translation\Loader\MoFileLoader()));
$instance->addLoader('ts', ($this->privates['translation.loader.qt'] ?? $this->privates['translation.loader.qt'] = new \Symfony\Component\Translation\Loader\QtFileLoader()));
$instance->addLoader('csv', ($this->privates['translation.loader.csv'] ?? $this->privates['translation.loader.csv'] = new \Symfony\Component\Translation\Loader\CsvFileLoader()));
$instance->addLoader('res', ($this->privates['translation.loader.res'] ?? $this->privates['translation.loader.res'] = new \Symfony\Component\Translation\Loader\IcuResFileLoader()));
$instance->addLoader('dat', ($this->privates['translation.loader.dat'] ?? $this->privates['translation.loader.dat'] = new \Symfony\Component\Translation\Loader\IcuDatFileLoader()));
$instance->addLoader('ini', ($this->privates['translation.loader.ini'] ?? $this->privates['translation.loader.ini'] = new \Symfony\Component\Translation\Loader\IniFileLoader()));
$instance->addLoader('json', ($this->privates['translation.loader.json'] ?? $this->privates['translation.loader.json'] = new \Symfony\Component\Translation\Loader\JsonFileLoader()));

return $instance;

Вы видите, что загрузчики не вводятся, когда я делаю украшение ...

Ответы [ 2 ]

0 голосов
/ 17 октября 2018

Мне удалось заставить его работать ... но, пожалуйста, не стесняйтесь комментировать

Мне пришлось создать TranslatorPass, чтобы добавить загрузчики в файл внедрения службы украшения.

<?php

namespace App\Translation\DependencyInjection;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use App\Translation\Reader\TranslationReader;

class TranslatorPass implements CompilerPassInterface
{
    private $readerServiceId;
    private $loaderTag;

    public function __construct(string $readerServiceId = TranslationReader::class, string $loaderTag = 'translation.loader')
    {
        $this->readerServiceId = $readerServiceId;
        $this->loaderTag = $loaderTag;
    }

    public function process(ContainerBuilder $container)
    {
        $loaders = array();
        $loaderRefs = array();
        foreach ($container->findTaggedServiceIds($this->loaderTag, true) as $id => $attributes) {
            $loaderRefs[$id] = new Reference($id);
            $loaders[$id][] = $attributes[0]['alias'];
            if (isset($attributes[0]['legacy-alias'])) {
                $loaders[$id][] = $attributes[0]['legacy-alias'];
            }
        }

        if ($container->hasDefinition($this->readerServiceId)) {
            $definition = $container->getDefinition($this->readerServiceId);
            foreach ($loaders as $id => $formats) {
                foreach ($formats as $format) {
                    $definition->addMethodCall('addLoader', array($format, $loaderRefs[$id]));
                }
            }
        }
    }
}

Я положил это в Kernel.php

protected function build(ContainerBuilder $container)
{
    parent::build($container);
    $container->addCompilerPass(new TranslatorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 1000);
}

затем

bin/console cache:clear

и вуаля!

0 голосов
/ 16 октября 2018

Я точно не уверен, что это корень вашей проблемы, но вот несколько замечаний.Надеемся, что это поможет вам найти решение, хотя на самом деле мне не дан полный ответ на ваш вопрос.

1) Некоторые службы перевода в Symfony называются only во время прогрева кэша.фаза.Всякий раз, когда вы изменяете свою конфигурацию или делаете bin/console cache:clear, вы увидите, что эти классы запущены, и они генерируют переводы в вашей папке var/cache/<env>/translations/.

2) Вы можете убедиться, что в вашемкеш, класс, загруженный var/cache/<env>/Container<...>/getTranslation_ReaderService.php, принадлежит вам, а не по умолчанию, например:

$this->privates['translation.reader'] = 
    new \Symfony\Component\Translation\Reader\TranslationReader();

3) Я также столкнулся с подобной проблемой в среде dev, где я пытался заменить Symfony\Component\Translation\Translator с моим собственным сервисом, и мне не удалось сначала вызвать мои методы.Часть объяснения состояла в том, что когда Symfony Profiler включен, Symfony делает что-то вроде этого (в src<env>DebugProjectContainer.php>):

$this->services['translator'] = new \Symfony\Component\Translation\DataCollectorTranslator(
    ($this->privates['translator.default'] ?? $this->getTranslator_DefaultService())
);

, а сам DataCollectorTranslator является оберткой для любого переводчика, который он получает в качестве своегоаргумент конструктора.

Я знаю, что это не идеальный ответ, но, надеюсь, это поможет вам найти путь к решению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...