How to setup a Translate Controller Plugin in Zend Framework 3

Sometimes in our Zend Framework 3 multi-language application, we could need to access to Zend Translator component directly from Controllers. For example, when we have to translate a string to return in a JsonModel.

So, let’s see how to write a very simple Controller Plugin that will help us to save a lot of code (and time).

Following explanation will assume we just have at least a Skeleton ZF3 Application with working Zend Translator component.

First of all, we have to write our plugin that will take Zend Translator object in constructor and will wrap its translate() method. So let’s add following file module/Application/src/Controller/Plugin/TranslatePlugin.php:

<?php
namespace Application\Controller\Plugin;

class TranslatorPlugin extends \Zend\Mvc\Controller\Plugin\AbstractPlugin
{
    /**
     * @var \Zend\I18n\Translator\Translator
     */
    protected $translator;

    function __construct(\Zend\I18n\Translator\Translator $translator)
    {
        $this->translator = $translator;
    }

    public function translate($string)
    {
        return $this->translator->translate($string);
    }
}

Now, we need a Factory class to initialize our plugin and inject in it the Zend Translator component. That class will be placed in module/Application/src/Controller/Plugin/Factory/TranslatorPluginFactory.php and will be something like:

<?php
namespace Application\Controller\Plugin\Factory;

class TranslatorPluginFactory implements \Zend\ServiceManager\Factory\FactoryInterface
{
    public function __invoke(\Interop\Container\ContainerInterface $container, $requestedName, array $options = null)
    {
        if (!$container->has('translator')) {
            throw new \Exception("Zend I18n Translator not configured");
        }
  
        $translator = $container->get('translator');
        return new \Application\Controller\Plugin\TranslatorPlugin($translator);
    }
}

Finally, we have to configure ZF3 application to load plugin by adding following lines to module/Application/config/module.config.php file:

<?php
return [
    'controller_plugins' => [
        'factories' => [
            'translator' => \Application\Controller\Plugin\Factory\TranslatorPluginFactory::class,
        ],
    ],
    ...
];

At this point, we can easily invoke our new plugin from each controller in application. For example we can do as following:

<?php
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        $translatedMessage = $this->translator()->translate('Message to be translated');
      
        return new JsonModel('message' => $translatedMessage);
    }
}

 

Articoli correlati

  • Matt .

    Thanks for this good detailed post but what I understood is that the controller_plugins will be removed in ZF4, so why not inject it where you need it ?

    Maybe a post without doing it as controller_plugin might be helpfull!

    • daredevel

      Hi Matt,
      thanks for your comment. Maybe I’ll write a post without injection.

      In the meantime, could you please share your information about ZF4?

      Thanks you.

      • Matt .

        Hi Valerio,

        Thanks for your quick reply! I understood that from some people that use ZF a lot and plugins are not a proper way like the old fashioned $this->getServiceLocator()->get() way so will be out. I’m not sure but it has been told.

        I came up to this as $this->getServiceLocator()->get() was used in my ZF2 project which I need to debug because of someone who made a lot of misstakes.

        Would be nice if you can write such a detailed post like this as I kinda need it and was googleing and found your blog!

        If I have some update I will post it but I’m pretty sure you are faster!