Integration of I18n function in Plates templates


#1

Hello everyone,

I followed this cookbook (https://docs.zendframework.com/zend-expressive/cookbook/setting-locale-without-routing-parameter/) and it works just fine to define the locale !

But I’m struggling to use the I18n functions inside my Plates templates. Now my locale is defined correctly, I have absolutely no idea how to translate the strings that are in my templates.

I tried to find documentation about that integration but couldn’t find any…
Can someone help me with that ?

Thanks a lot ! :slight_smile:


#2

Anyone has a suggestion on how do this ?

Thanks :slight_smile:


#3

Here is my solution :

Middleware

<?php

namespace App\Middleware;

use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Locale;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

class LocalizationMiddleware implements MiddlewareInterface
{
  public const LOCALIZATION_ATTRIBUTE = 'locale';

  public function process(ServerRequestInterface $request, DelegateInterface $delegate) : ResponseInterface
  {
    $cookies = $request->getCookieParams();
    $query = $request->getQueryParams();
    $server = $request->getServerParams();

    if (isset($query['lang']) && preg_match('/^(?P<locale>[a-z]{2,3}([-_][a-zA-Z]{2}|))$/', $query['lang'])) {
      Locale::setDefault(Locale::canonicalize($query['lang']));

      if (isset($cookies['lang'])) {
        setcookie('lang', FALSE, NULL, NULL, NULL, (!empty($server['HTTPS'])), FALSE);
      }
      setcookie('lang', Locale::getDefault(), NULL, NULL, NULL, (!empty($server['HTTPS'])), FALSE);
    } else if (isset($cookies['lang'])) {
      Locale::setDefault(Locale::canonicalize($cookies['lang']));
    } else if (isset($server['HTTP_ACCEPT_LANGUAGE']) ) {
      $locale = Locale::acceptFromHttp($server['HTTP_ACCEPT_LANGUAGE']);
      Locale::setDefault(Locale::canonicalize($locale));
    } else {
      Locale::setDefault('en_US');
    }

    return $delegate->process($request->withAttribute(self::LOCALIZATION_ATTRIBUTE, Locale::getDefault()));
  }
}

Extension

<?php

namespace App\Extension;

use League\Plates\Engine;
use League\Plates\Extension\ExtensionInterface;
use Zend\I18n\Translator\Translator;

class TranslateExtension implements ExtensionInterface
{
  private $translator;

  public function __construct(Translator $translator) {
    $this->translator = $translator;
  }

  public function register(Engine $engine)
  {
    $engine->registerFunction('translate', [$this, 'generateTranslate']);
  }

  public function generateTranslate(string $var) : string
  {
    return $this->translator->translate($var, 'my-application');
  }
}

Extension factory

<?php

namespace App\Extension\Factory;

use App\Extension\TranslateExtension;
use App\Middleware\LocalizationMiddleware;
use Psr\Container\ContainerInterface;
use Zend\I18n\Translator\Translator;

class TranslateFactory
{
  public function __invoke(ContainerInterface $container)
  {
    $translator = new Translator();
    $translator->addTranslationFilePattern('gettext', '../locale', '%s/my-application.mo', 'my-application');

    return new TranslateExtension($translator);
  }
}

Configuration

Edit config/templates.global.php :

<?php

use Zend\Expressive\Plates\PlatesRendererFactory;
use Zend\Expressive\Template\TemplateRendererInterface;

return [
  'dependencies' => [
    'factories' => [
      TemplateRendererInterface::class => PlatesRendererFactory::class,
      App\Extension\TranslateExtension::class => App\Extension\Factory\TranslateFactory::class,
    ],
  ],

  'templates' => [
    'extension' => 'phtml',
  ],

  'plates' => [
    'extensions' => [
      App\Extension\TranslateExtension::class,
    ],
  ]
];

Add the middleware in config/pipelines.php :

$app->pipe(App\Middleware\LocalizationMiddleware::class);

You can now use $this->translate() in your Plates templates :tada: