ZF2在控制器中使用翻译器
翻译通过Translator
完成。翻译器是一个对象,例如在视图助手中注入,所以如果你调用视图助手,它会使用翻译器来翻译你的字符串。对于这个答案,我假设你已经配置了翻译器just the same as the skeleton application。
最好的方法是使用工厂将它作为依赖注入到控制器中。控制器配置:
'controllers' => array(
'factories' => array(
'my-controller' => function($sm) {
$translator = $sm->getServiceLocator()->get('translator');
$controller = new MyModule\Controller\FooController($translator);
}
)
)
而且控制器本身:
namespace MyModule;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\I18n\Translator\Translator;
class FooController extends AbstractActionController
{
protected $translator;
public function __construct(Translator $translator)
{
$this->translator = $translator;
}
}
另一种方法是从你的行动服务管理器拉翻译,但这是不够灵活,更少的可测试性和难以维持:
public function fooAction()
{
$translator = $this->getServiceManager()->get('translator');
}
在这两种情况下,您都可以使用$translator->translate('foo bar baz')
来翻译字符串。
我想有一个最好的方式做到这一点:
$translator = $this->getServiceLocator()->get('translator');
$translator->translate('__your_key');
如果您想使用控制器译者就像在看,就是这样:
$this->translate('Hello')
,而不是丑陋 :
$this->getServiceLocator()->get('translator')->translate('Hello')
你也可以写为翻译插件控制器,就像查看帮手Zend\I18n\View\Helper\Translate
一样。
当然,你可以用相同的签名调用插件:
__invoke($message, $textDomain = null, $locale = null)
只需注册:
'controller_plugins' => array(
'factories' => array(
'translate' => 'Application\Controller\Plugin\Translate',
),
),
而写插件:
<?php
namespace Application\Controller\Plugin;
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\FactoryInterface;
use Zend\I18n\Translator\Translator;
class Translate implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$serviceLocator = $serviceLocator->getController()->getServiceLocator();
$serviceFactory = new TranslatorServiceFactory();
$translator = $serviceFactory->createService($serviceLocator);
return new TranslatorProxy($translator);
}
}
final class TranslatorProxy extends AbstractPlugin
{
private $translator;
public function __construct(Translator $translator)
{
$this->translator = $translator;
}
public function __invoke($message, $textDomain = 'default', $locale = null)
{
return $this->translator->translate($message, $textDomain, $locale);
}
public function __call($method, $args)
{
return call_user_func_array([$this->translator, $method], $args);
}
public static function __callstatic($method, $args)
{
return call_user_func_array([$this->translator, $method], $args);
}
}
它是如何工作的? 你看,ServiceLocator
传递
createService(ServiceLocatorInterface $serviceLocator)
厂配置空间controller_plugins
,并在控制器不能访问Config
服务ServiceLocator
。因此,您无法获取配置并通过TranslatorServiceFactory
创建对象Translate
。
取而代之的是,您可以通过输入$serviceLocator->getController()
来访问分配给已为其调用助手的控制器的ServiceLocator
。
当然,在$serviceLocator
方法createService
传递是Zend\Mvc\Controller\PluginManager
实例。
为什么代理? 通过插件工厂返回的对象必须实现
Zend\Mvc\Controller\Plugin\PluginInterface
这是在
Zend\Mvc\Controller\Plugin\AbstractPlugin
抽象实现,所以我们创建的代理对象从我们的插件到Translate
对象的所有呼叫。
希望它有帮助!
我在我自己的博客上发表了一篇文章。
你可以这样来做:
$translate = $this->getServiceLocator()->get('viewhelpermanager')->get('translate');
$translator = $this->getServiceManager()->get('MVCTranslator');
在我的情况下完美的作品这个解决方案:
namespace MyNS;
class MyCtrlr
{
protected $translator;
public function getTranslator()
{
if (!$this->translator)
{
$sm = $this->getServiceLocator();
$this->translator = $sm->get('translator');
}
return $this->translator;
}
public function myAction()
{
$sTrHello = $this->getTranslator()->translate('Hello');
/*
* More code here
*/
}
}
的可调用是可以不带任何参数来构建一个类。由于我们的MyModule \ Controller \ FooController现在有一个必需的参数,我们需要改变它。 A 工厂是创建另一个类的实例的类。我们现在将为我们的FooController创建一个。让我们修改module.config.php文件是这样的:
return array(
'view_manager' => array(/** ViewManager Config */),
'controllers' => array(
'invokables' => array(
//'MyModule\Controller\Foo' => 'MyModule\Controller\FooController'
),
'factories' => array(
'MyModule\Controller\Foo' => 'MyModule\Factory\FooControllerFactory',
)
),
'router' => array(/** Router Config */)
);
让我们实现我们的工厂类,这在创建一个新的文件夹\模块\ MyModule中的\ src \ MyModule的\厂和所谓的新文件FooControllerFactory .PHP:
<?php
namespace MyModule\Factory;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use MyModule\Controller\FooController;
class FooControllerFactory implements FactoryInterface
{
public function __construct()
{}
/**
* Create service
*
* @param ServiceLocatorInterface $serviceLocator
*
* @return mixed
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$realServiceLocator = $serviceLocator->getServiceLocator();
$translator = $realServiceLocator->get('translator');
return new FooController($translator);
}
}
我们现在使用的$翻译我们FooController的内。为此,我们将需要覆盖默认__contruct():
<?php
namespace MyModule\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\Mvc\I18n\Translator;
class FooController extends AbstractActionController
{
protected $translator;
public function __construct(Translator $translator)
{
$this->translator = $translator;
}
public function FooAction()
{
...
$msg = $this->translator->translate('Blah blah blah');
...
}
}
在我的情况下正常工作!
最新版本的ZF2将翻译器的关键字更改为“MVCTranslator”。 – MKroeders
不适用于我。我有以下错误: 可捕获的致命错误:参数1传递给Application \ Controller \ CorrespondenciasController :: __ construct()必须是Zend \ I18n \ Translator \ Translator的实例,没有给出,在/ home/inhotim中调用/Trabalho/0-OPE/scape/Products/ oo/Web/landscape /vendor/zendframework/zend-servicemanager/src/AbstractPluginManager.php 207行,并在/ home/inhotim/Trabalho/0-OPE/scape中定义/Produção/Web/scape/module/Application/src/Application/Controller/CorrespondenciasController.phpon line 141 –
@GustavoGonçalves这意味着你的工厂不工作。检查我的答案中的第一个代码块。 –