我正在使用Symfony(2.7.4)网站,其中一些用户拥有自己的语言资源用于他们自己的语言环境。例如,用户可能有两个区域设置(例如fr
和en
),另一个用户也可能有一个或所有这些区域设置。
每个用户都可以在第三方应用中编辑自己的翻译,因此不会在用户之间共享翻译。
我希望能够在访问用户页面时根据区域设置(在URL中定义)和用户(可能是其ID)加载相应的(YML或XLIFF)资源文件或任何识别它的东西。)
例如,访问user99.my-domain.ext/fr/
时,我想将[base_directory]/user99/messages.fr.yml
添加到转换程序加载的资源中,以便覆盖基础messages.fr.yml
中的密钥。
我试图在我的服务中注入译者,但我只能用它来阅读翻译,而不是添加任何翻译。最好的方法是什么?或者在服务中这样做太晚了?也许内核是一个更好的地方?
感谢任何帮助!
注意:我在我的示例中使用了YAML格式,但任何Symfony已知格式都符合条件。
答案 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 }}
我希望这有帮助,谢谢!