Symfony:从服务中将资源加载到转换器中

时间:2015-09-24 10:24:38

标签: php symfony

我正在使用Symfony(2.7.4)网站,其中一些用户拥有自己的语言资源用于他们自己的语言环境。例如,用户可能有两个区域设置(例如fren),另一个用户也可能有一个或所有这些区域设置。

每个用户都可以在第三方应用中编辑自己的翻译,因此不会在用户之间共享翻译。

我希望能够在访问用户页面时根据区域设置(在URL中定义)和用户(可能是其ID)加载相应的(YML或XLIFF)资源文件或任何识别它的东西。)

例如,访问user99.my-domain.ext/fr/时,我想将[base_directory]/user99/messages.fr.yml添加到转换程序加载的资源中,以便覆盖基础messages.fr.yml中的密钥。

我试图在我的服务中注入译者,但我只能用它来阅读翻译,而不是添加任何翻译。最好的方法是什么?或者在服务中这样做太晚了?也许内核是一个更好的地方?

感谢任何帮助!

注意:我在我的示例中使用了YAML格式,但任何Symfony已知格式都符合条件。

2 个答案:

答案 0 :(得分:0)

为了“覆盖”翻译,您应该装饰translator服务。这样,在某处调用trans()时,将执行您自己的翻译逻辑。

http://symfony.com/doc/current/components/dependency_injection/advanced.html#decorating-services

通过装饰服务,其他捆绑包也将开始使用您在上面描述的逻辑。您可以注入活动用户(例如token_storage服务)和一些缓存服务(例如https://github.com/doctrine/DoctrineCacheBundle)以确保您的用户获得正确的翻译。

这与请求或主机名无关,用户的转换逻辑应在执行防火墙/授权逻辑后发生。

请参阅Symfony的LoggingTranslator PR,了解如何使用装饰器模式让翻译人员记录缺少的翻译:https://github.com/symfony/symfony/pull/10887/files

答案 1 :(得分:0)

我选择使用自定义Twig过滤器,因此我可以决定何时需要特定于用户的翻译以及何时需要通用翻译。

这是我的扩展程序(我的用户实际上是Domain个实例):

<?php

// src/AppBundle/Twig/DomainTranslationExtension

namespace AppBundle\Twig;

use AppBundle\Document\Domain;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Translation\Loader\YamlFileLoader;
use Symfony\Component\Translation\Translator;

class DomainTranslationExtension extends \Twig_Extension {

    /**
     * @var ContainerInterface
     */
    protected $container;

    /**
     * @var Translator
     */
    protected $translator;

    /**
     * @var string
     */
    protected $locale;

    /**
     * @var Domain
     */
    protected $domain;

    public function setContainer(ContainerInterface $container) {
        $this->container = $container;
        $this->locale = $this->container->get('request_stack')->getMasterRequest()->getLocale();

        $domainService = $this->container->get('app.domain_service');
        $this->domain = $domainService->getDomain();

        // TODO: File loading error check
        $this->translator = new Translator($this->locale);
        $this->translator->addLoader('yaml', new YamlFileLoader());
        $this->translator->addResource('yaml', 'path/to/domain-translations/' . $this->domain->getSlug() . '/messages.' . $this->locale . '.yml', $this->locale);
    }

    public function getFilters() {
        return array(
            new \Twig_SimpleFilter('transDomain', array($this, 'transDomain')),
        );
    }

    public function transDomain($s) {
        $trans = $this->translator->trans($s);
        // Falling back to default translation if custom isn't available
        if ($trans == $s) {
            $trans = $this->container->get('translator')->trans($s);
        }
        return $trans;
    }

    public function getName() {
        return 'app_translation_extension';
    }

}

app/config/services.yml中声明:

app.domain_service:
    class: AppBundle\Services\DomainService
    arguments: [ @request_stack, @doctrine_mongodb, @translation.loader ]

并在Twig文件中使用:

{{ 'my.translation.key'|transDomain }}

我希望这有帮助,谢谢!