首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >更换/装饰`translation.reader`

更换/装饰`translation.reader`
EN

Stack Overflow用户
提问于 2018-10-16 16:23:37
回答 2查看 387关注 0票数 2

我填补了一个漏洞,但它接缝我要离开: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\TranslationReaderApp\Translation\Reader\TranslationReader

遵循decoration.html

修改services.yaml

代码语言:javascript
复制
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

代码语言:javascript
复制
<?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();

默认情况下,它看起来如下:

代码语言:javascript
复制
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;

你可以看到装载机没有被注入当我做装饰..。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-10-17 15:58:44

我设法让它运转起来..。但请随时评论

我必须创建一个TranslatorPass来将加载器添加到装饰服务注入文件中。

代码语言:javascript
复制
<?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

代码语言:javascript
复制
protected function build(ContainerBuilder $container)
{
    parent::build($container);
    $container->addCompilerPass(new TranslatorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 1000);
}

然后

代码语言:javascript
复制
bin/console cache:clear

等等!

票数 1
EN

Stack Overflow用户

发布于 2018-10-16 17:07:39

我不确定这是否是你问题的根源,但这里有一些评论。希望这将帮助你找到一个解决办法,即使我实际上并没有给你的问题一个完整的答案。

1) Symfony中的一些翻译服务仅在缓存预热阶段调用。每当您更改配置或执行bin/console cache:clear时,都会看到这些类正在运行,并在您的var/cache/<env>/translations/文件夹中生成翻译。

2)您可以尝试确保缓存中var/cache/<env>/Container<...>/getTranslation_ReaderService.php加载的类是您的,而不是默认的,如下所示:

代码语言:javascript
复制
$this->privates['translation.reader'] = 
    new \Symfony\Component\Translation\Reader\TranslationReader();

3)在dev环境中,我也遇到了一个类似的问题,当时我试图用自己的服务替换Symfony\Component\Translation\Translator,但一开始我没有设法调用我的方法。部分解释是,当启用Symfony Profiler时,Symfony会执行类似的操作(在src<env>DebugProjectContainer.php>中):

代码语言:javascript
复制
$this->services['translator'] = new \Symfony\Component\Translation\DataCollectorTranslator(
    ($this->privates['translator.default'] ?? $this->getTranslator_DefaultService())
);

DataCollectorTranslator本身是一个包装器,不管它得到哪个转换器作为它的构造函数参数。

我知道这不是一个完美的答案,但希望这能帮助你找到解决办法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52839966

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档