ZF2在控制器中使用转换器

dir*_*ory 8 translation controller zend-framework2

对于URL重定向,我需要在控制器中翻译某些内容.

我如何访问$ this-> translate(); 在控制器?

谢谢!缺口

Jur*_*man 17

翻译是通过一个Translator.翻译器是一个对象,例如在视图助手中注入,因此如果您调用该视图助手,它将使用翻译器来翻译您的字符串.对于这个答案,我假设你已经配置了与骨架应用程序相同的翻译.

最好的方法是使用工厂将其作为依赖项注入控制器.控制器配置:

'controllers' => array(
  'factories' => array(
    'my-controller' => function($sm) {
      $translator = $sm->getServiceLocator()->get('translator');
      $controller = new MyModule\Controller\FooController($translator);
    }
  )
)
Run Code Online (Sandbox Code Playgroud)

而控制器本身:

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是在您的操作中从服务管理器中提取翻译器,但这不太灵活,不太可测试且难以维护:

public function fooAction()
{
  $translator = $this->getServiceManager()->get('translator');
}
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,您都可以使用$translator->translate('foo bar baz')翻译字符串.


Ath*_*lan 11

如果你想在视图中使用控制器中的翻译器,就像那样:

$this->translate('Hello')
Run Code Online (Sandbox Code Playgroud)

而不是丑陋的:

$this->getServiceLocator()->get('translator')->translate('Hello')
Run Code Online (Sandbox Code Playgroud)

您也可以为控制器编写translate插件,就像查看助手一样Zend\I18n\View\Helper\Translate.

当然,您可以使用相同的签名调用插件:

__invoke($message, $textDomain = null, $locale = null)
Run Code Online (Sandbox Code Playgroud)

只需注册:

'controller_plugins' => array(
    'factories' => array(
        'translate' => 'Application\Controller\Plugin\Translate',
    ),
),
Run Code Online (Sandbox Code Playgroud)

并编写插件:

<?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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这个怎么运作? 你看,ServiceLocator传入

createService(ServiceLocatorInterface $serviceLocator)
Run Code Online (Sandbox Code Playgroud)

在配置空间中的工厂,controller_plugins无法访问控制器中的Config服务ServiceLocator.因此,您无法获取配置并Translate通过创建对象TranslatorServiceFactory.

而不是那样,您可以ServiceLocator通过键入来访问已分配给已调用我们的帮助程序的控制器$serviceLocator->getController().

当然,$serviceLocator传入createService方法就是实例Zend\Mvc\Controller\PluginManager.

为何代理? 通过插件工厂返回的对象必须实现

Zend\Mvc\Controller\Plugin\PluginInterface
Run Code Online (Sandbox Code Playgroud)

这是抽象地实现的

Zend\Mvc\Controller\Plugin\AbstractPlugin
Run Code Online (Sandbox Code Playgroud)

所以我们创建了代理对象来将我们插件中的所有调用转发给Translate对象.

希望它有所帮助!

我在自己的博客上发表了一篇文章.