我填补了一个错误,但它表明我已经离开了: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
关注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;
您可以看到我进行装饰时没有注入装载器...
答案 0 :(得分:1)
我不确定这是否是您问题的根源,但是这里有一些说明。希望这会帮助您找到解决方案,即使实际上您的问题并未得到我的完整答复。
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
本身是包装器,用于作为构造函数参数的翻译器。
我知道这不是一个完美的答案,但希望这将帮助您找到解决方案的方法。
答案 1 :(得分:0)
我设法使其发挥作用...但是请随时发表评论
我必须创建一个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
etvoilà!