Added translation support for twig templates

See https://twig-extensions.readthedocs.io/en/latest/i18n.html for documentation
This commit is contained in:
Igor Scheller 2018-08-29 15:29:48 +02:00
parent a2c47304d8
commit 8257864829
7 changed files with 162 additions and 6 deletions

View File

@ -29,6 +29,7 @@
"symfony/http-foundation": "^3.3", "symfony/http-foundation": "^3.3",
"symfony/psr-http-message-bridge": "^1.0", "symfony/psr-http-message-bridge": "^1.0",
"twbs/bootstrap": "^3.3", "twbs/bootstrap": "^3.3",
"twig/extensions": "^1.5",
"twig/twig": "^2.5", "twig/twig": "^2.5",
"zendframework/zend-diactoros": "^1.7" "zendframework/zend-diactoros": "^1.7"
}, },

View File

@ -10,13 +10,13 @@ return [
\Engelsystem\Config\ConfigServiceProvider::class, \Engelsystem\Config\ConfigServiceProvider::class,
\Engelsystem\Http\UrlGeneratorServiceProvider::class, \Engelsystem\Http\UrlGeneratorServiceProvider::class,
\Engelsystem\Renderer\RendererServiceProvider::class, \Engelsystem\Renderer\RendererServiceProvider::class,
\Engelsystem\Renderer\TwigServiceProvider::class,
\Engelsystem\Database\DatabaseServiceProvider::class, \Engelsystem\Database\DatabaseServiceProvider::class,
\Engelsystem\Http\RequestServiceProvider::class, \Engelsystem\Http\RequestServiceProvider::class,
\Engelsystem\Http\SessionServiceProvider::class, \Engelsystem\Http\SessionServiceProvider::class,
\Engelsystem\Helpers\TranslationServiceProvider::class, \Engelsystem\Helpers\TranslationServiceProvider::class,
\Engelsystem\Http\ResponseServiceProvider::class, \Engelsystem\Http\ResponseServiceProvider::class,
\Engelsystem\Http\Psr7ServiceProvider::class, \Engelsystem\Http\Psr7ServiceProvider::class,
\Engelsystem\Renderer\TwigServiceProvider::class,
\Engelsystem\Middleware\RouteDispatcherServiceProvider::class, \Engelsystem\Middleware\RouteDispatcherServiceProvider::class,
\Engelsystem\Middleware\RequestHandlerServiceProvider::class, \Engelsystem\Middleware\RequestHandlerServiceProvider::class,
], ],

View File

@ -0,0 +1,57 @@
<?php
namespace Engelsystem\Renderer\Twig\Extensions;
use Engelsystem\Helpers\Translator;
use Twig_Extension as TwigExtension;
use Twig_Extensions_TokenParser_Trans as TranslationTokenParser;
use Twig_Filter as TwigFilter;
use Twig_Function as TwigFunction;
use Twig_TokenParserInterface as TwigTokenParser;
class Translation extends TwigExtension
{
/** @var Translator */
protected $translator;
/** @var TranslationTokenParser */
protected $tokenParser;
/**
* @param Translator $translator
* @param TranslationTokenParser $tokenParser
*/
public function __construct(Translator $translator, TranslationTokenParser $tokenParser)
{
$this->translator = $translator;
$this->tokenParser = $tokenParser;
}
/**
* @return array
*/
public function getFilters()
{
return [
new TwigFilter('trans', [$this->translator, 'translate']),
];
}
/**
* @return TwigFunction[]
*/
public function getFunctions()
{
return [
new TwigFunction('__', [$this->translator, 'translate']),
];
}
/**
* @return TwigTokenParser[]
*/
public function getTokenParsers()
{
return [$this->tokenParser];
}
}

View File

@ -6,6 +6,7 @@ use Engelsystem\Container\ServiceProvider;
use Engelsystem\Renderer\Twig\Extensions\Config; use Engelsystem\Renderer\Twig\Extensions\Config;
use Engelsystem\Renderer\Twig\Extensions\Globals; use Engelsystem\Renderer\Twig\Extensions\Globals;
use Engelsystem\Renderer\Twig\Extensions\Session; use Engelsystem\Renderer\Twig\Extensions\Session;
use Engelsystem\Renderer\Twig\Extensions\Translation;
use Engelsystem\Renderer\Twig\Extensions\Url; use Engelsystem\Renderer\Twig\Extensions\Url;
use Twig_Environment as Twig; use Twig_Environment as Twig;
use Twig_LoaderInterface as TwigLoaderInterface; use Twig_LoaderInterface as TwigLoaderInterface;
@ -14,10 +15,11 @@ class TwigServiceProvider extends ServiceProvider
{ {
/** @var array */ /** @var array */
protected $extensions = [ protected $extensions = [
'config' => Config::class, 'config' => Config::class,
'globals' => Globals::class, 'globals' => Globals::class,
'session' => Session::class, 'session' => Session::class,
'url' => Url::class, 'url' => Url::class,
'translation' => Translation::class,
]; ];
public function register() public function register()

View File

@ -1,6 +1,6 @@
{% extends "layouts/app.twig" %} {% extends "layouts/app.twig" %}
{% block title %}Error {{ status }}{% endblock %} {% block title %}{% if status == 404 %}{{ __("Page not found") }}{% else %}Error {{ status }}{% endif %}{% endblock %}
{% block content %} {% block content %}
<div class="alert alert-info">{{ content }}</div> <div class="alert alert-info">{{ content }}</div>

View File

@ -7,6 +7,27 @@ use Twig_Function as TwigFunction;
abstract class ExtensionTest extends TestCase abstract class ExtensionTest extends TestCase
{ {
/**
* Assert that a twig filter was registered
*
* @param string $name
* @param callable $callback
* @param TwigFunction[] $functions
*/
protected function assertFilterExists($name, $callback, $functions)
{
foreach ($functions as $function) {
if ($function->getName() != $name) {
continue;
}
$this->assertEquals($callback, $function->getCallable());
return;
}
$this->fail(sprintf('Filter %s not found', $name));
}
/** /**
* Assert that a twig function was registered * Assert that a twig function was registered
* *
@ -45,4 +66,19 @@ abstract class ExtensionTest extends TestCase
$this->fail(sprintf('Global %s not found', $name)); $this->fail(sprintf('Global %s not found', $name));
} }
/**
* Assert that a token parser was set
*
* @param $tokenParser
* @param $tokenParsers
*/
protected function assertTokenParserExists($tokenParser, $tokenParsers)
{
$this->assertArraySubset(
[$tokenParser],
$tokenParsers,
sprintf('Token parser %s not found', get_class($tokenParser))
);
}
} }

View File

@ -0,0 +1,60 @@
<?php
namespace Engelsystem\Test\Unit\Renderer\Twig\Extensions;
use Engelsystem\Helpers\Translator;
use Engelsystem\Renderer\Twig\Extensions\Translation;
use PHPUnit\Framework\MockObject\MockObject;
use Twig_Extensions_TokenParser_Trans as TranslationTokenParser;
class TranslationTest extends ExtensionTest
{
/**
* @covers \Engelsystem\Renderer\Twig\Extensions\Translation::__construct
* @covers \Engelsystem\Renderer\Twig\Extensions\Translation::getFilters
*/
public function testGeFilters()
{
/** @var Translator|MockObject $translator */
$translator = $this->createMock(Translator::class);
/** @var TranslationTokenParser|MockObject $parser */
$parser = $this->createMock(TranslationTokenParser::class);
$extension = new Translation($translator, $parser);
$filters = $extension->getFilters();
$this->assertExtensionExists('trans', [$translator, 'translate'], $filters);
}
/**
* @covers \Engelsystem\Renderer\Twig\Extensions\Translation::getFunctions
*/
public function testGetFunctions()
{
/** @var Translator|MockObject $translator */
$translator = $this->createMock(Translator::class);
/** @var TranslationTokenParser|MockObject $parser */
$parser = $this->createMock(TranslationTokenParser::class);
$extension = new Translation($translator, $parser);
$functions = $extension->getFunctions();
$this->assertExtensionExists('__', [$translator, 'translate'], $functions);
}
/**
* @covers \Engelsystem\Renderer\Twig\Extensions\Translation::getTokenParsers
*/
public function testGetTokenParsers()
{
/** @var Translator|MockObject $translator */
$translator = $this->createMock(Translator::class);
/** @var TranslationTokenParser|MockObject $parser */
$parser = $this->createMock(TranslationTokenParser::class);
$extension = new Translation($translator, $parser);
$tokenParsers = $extension->getTokenParsers();
$this->assertTokenParserExists($parser, $tokenParsers);
}
}