9

对于 url 重定向,我需要在控制器中翻译一些东西。

我怎样才能访问 $this->translate(); 在控制器中?

谢谢!缺口

4

7 回答 7

18

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

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

'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')来翻译您的字符串。

于 2013-01-10T18:07:24.080 回答
11

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

$this->translate('Hello')

而不是丑陋

$this->getServiceLocator()->get('translator')->translate('Hello')

你也可以为控制器编写翻译插件,就像 view helper 一样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。因此,您无法通过 获取配置和创建Translate对象TranslatorServiceFactory

取而代之的是,您可以通过键入来访问ServiceLocator分配给我们的助手已为其调用的控制器$serviceLocator->getController()

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

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

Zend\Mvc\Controller\Plugin\PluginInterface

这是抽象实现的

Zend\Mvc\Controller\Plugin\AbstractPlugin

所以我们创建了代理对象来将我们插件的所有调用转发到该Translate对象。

希望它有所帮助!

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

于 2013-06-29T19:00:33.200 回答
1

我想有一个最好的方法来做到这一点:

$translator = $this->getServiceLocator()->get('translator');
$translator->translate('__your_key');
于 2013-02-15T14:17:17.040 回答
0
$translator = $this->getServiceManager()->get('MVCTranslator');
于 2015-02-10T17:22:58.053 回答
0

在我的情况下,这个解决方案非常有效:

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
         */
    }

}
于 2015-06-19T12:42:22.003 回答
0

调用是可以在没有任何参数的情况下构造的类。由于我们的MyModule\Controller\FooController现在有一个必需的参数,我们需要更改它。工厂是创建另一个类的实例的类。我们现在将为我们的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 */ )
 );

让我们实现我们的工厂类,为此在\module\MyModule\src\MyModule\Factory中创建一个新文件夹和名为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中使用$translator。为此,我们需要覆盖默认的__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');
      ...
    }
}

在我的情况下工作正常!!!

于 2017-05-12T09:07:01.007 回答
-1

你可以这样做:

$translate = $this->getServiceLocator()->get('viewhelpermanager')->get('translate');
于 2014-08-15T14:04:13.240 回答