Reputation: 3169
For a url redirection I need to translate something in the controller.
How can I acces $this->translate(); in the controller?
Thanks! Nick
Upvotes: 9
Views: 15385
Reputation: 11
An invokable is a class that can be constructed without any arguments. Since our MyModule\Controller\FooController now has a required argument, we need to change this. A factory is a class that creates instances of another class. We’ll now create one for our FooController. Let’s modify our module.config.php file like this:
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 */ )
);
Let’s implement our factory class, for this create a new folder in \module\MyModule\src\MyModule\Factory and new file called 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);
}
}
Let’s now use the $translator within our FooController. For this we will need to overwrite the default __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');
...
}
}
In my case works fine!!!
Upvotes: 0
Reputation: 23
In my case works perfectly this solution:
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
*/
}
}
Upvotes: 0
Reputation: 963
$translator = $this->getServiceManager()->get('MVCTranslator');
Upvotes: 0
Reputation: 326
You may do it this way:
$translate = $this->getServiceLocator()->get('viewhelpermanager')->get('translate');
Upvotes: -1
Reputation: 6619
If you want to use the translator in controller like in view, just like that:
$this->translate('Hello')
instead of ugly:
$this->getServiceLocator()->get('translator')->translate('Hello')
you can also write the translate plugin for controller, just like view helper Zend\I18n\View\Helper\Translate
.
Of course, you can invoke the plugin with the same signature:
__invoke($message, $textDomain = null, $locale = null)
Just register:
'controller_plugins' => array(
'factories' => array(
'translate' => 'Application\Controller\Plugin\Translate',
),
),
And write plugin:
<?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);
}
}
How it works?
You see, the ServiceLocator
passed in
createService(ServiceLocatorInterface $serviceLocator)
factory in configuration space controller_plugins
, does have no access to the Config
service in ServiceLocator
in controller. So you cannot get the configuration and create the Translate
object via TranslatorServiceFactory
.
Instead of that, you can access to the ServiceLocator
assigned to the controller for which our helper has been invoked, by typing $serviceLocator->getController()
.
Of course, $serviceLocator
passed in createService
method is instance of Zend\Mvc\Controller\PluginManager
.
Why proxy? The object returned via plugin factory has to implement
Zend\Mvc\Controller\Plugin\PluginInterface
which is abstractly implemented in
Zend\Mvc\Controller\Plugin\AbstractPlugin
so we created proxy object to forward all calls from our plugin to the Translate
object.
Hope it helped!
I have published an article in my own blog.
Upvotes: 11
Reputation: 499
I guess there's a nicest way to do it :
$translator = $this->getServiceLocator()->get('translator');
$translator->translate('__your_key');
Upvotes: 1
Reputation: 13558
Translation is done via a Translator
. The translator is an object and injected for example in a view helper, so if you call that view helper, it uses the translator to translate your strings. For this answer I assume you have configured the translator just the same as the skeleton application.
The best way is to use the factory to inject this as a dependency into your controller. The controller config:
'controllers' => array(
'factories' => array(
'my-controller' => function($sm) {
$translator = $sm->getServiceLocator()->get('translator');
$controller = new MyModule\Controller\FooController($translator);
}
)
)
And the controller itself:
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;
}
}
An alternative is to pull the translator from the service manager in your action, but this is less flexible, less testable and harder to maintain:
public function fooAction()
{
$translator = $this->getServiceManager()->get('translator');
}
In both cases you can use $translator->translate('foo bar baz')
to translate your strings.
Upvotes: 18