added event to manage javascript translations (#2104)

This commit is contained in:
Kevin Papst
2020-11-09 13:28:22 +01:00
committed by GitHub
parent 66865b553e
commit bd4efad22b
7 changed files with 127 additions and 25 deletions

View File

@@ -0,0 +1,64 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Event;
use Symfony\Contracts\EventDispatcher\Event;
final class ThemeJavascriptTranslationsEvent extends Event
{
/**
* Contains default translations for all views.
*
* For usage see "templates/base.html.twig" in block "javascripts".
*
* Structure
* ---------
* Javascript key: [Translation key, Translation domain]
*
* @var array<string, array<int, string>>
*/
private $translations = [
'confirm' => ['confirm', 'messages'],
'cancel' => ['cancel', 'messages'],
'today' => ['daterangepicker.today', 'daterangepicker'],
'yesterday' => ['daterangepicker.yesterday', 'daterangepicker'],
'lastWeek' => ['daterangepicker.lastWeek', 'daterangepicker'],
'thisWeek' => ['daterangepicker.thisWeek', 'daterangepicker'],
'lastMonth' => ['daterangepicker.lastMonth', 'daterangepicker'],
'thisMonth' => ['daterangepicker.thisMonth', 'daterangepicker'],
'lastYear' => ['daterangepicker.lastYear', 'daterangepicker'],
'thisYear' => ['daterangepicker.thisYear', 'daterangepicker'],
'customRange' => ['daterangepicker.customRange', 'daterangepicker'],
'timesheet.start.success' => ['timesheet.start.success', 'flashmessages'],
'timesheet.start.error' => ['timesheet.start.error', 'flashmessages'],
'timesheet.start.exceeded_limit' => ['timesheet.start.exceeded_limit', 'flashmessages'],
'timesheet.stop.success' => ['timesheet.stop.success', 'flashmessages'],
'timesheet.stop.error' => ['timesheet.stop.error', 'flashmessages'],
'action.update.success' => ['action.update.success', 'flashmessages'],
'action.update.error' => ['action.update.error', 'flashmessages'],
'action.delete.success' => ['action.delete.success', 'flashmessages'],
'action.delete.error' => ['action.delete.error', 'flashmessages'],
'confirm.delete' => ['confirm.delete', 'messages'],
'delete' => ['action.delete', 'messages'],
'login.required' => ['login_required', 'messages'],
];
public function getTranslations(): array
{
return $this->translations;
}
public function setTranslation(string $key, string $translationKey, string $translationDomain = 'messages'): ThemeJavascriptTranslationsEvent
{
$this->translations[$key] = [$translationKey, $translationDomain];
return $this;
}
}

View File

@@ -22,6 +22,7 @@ class EventExtensions extends AbstractExtension
{
return [
new TwigFunction('trigger', [ThemeEventExtension::class, 'trigger']),
new TwigFunction('javascript_translations', [ThemeEventExtension::class, 'getJavascriptTranslations']),
];
}
}

View File

@@ -10,6 +10,7 @@
namespace App\Twig\Runtime;
use App\Event\ThemeEvent;
use App\Event\ThemeJavascriptTranslationsEvent;
use App\Security\CurrentUser;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Twig\Extension\RuntimeExtensionInterface;
@@ -46,4 +47,13 @@ final class ThemeEventExtension implements RuntimeExtensionInterface
return $themeEvent;
}
public function getJavascriptTranslations(): array
{
$event = new ThemeJavascriptTranslationsEvent();
$this->eventDispatcher->dispatch($event);
return $event->getTranslations();
}
}

View File

@@ -239,29 +239,9 @@
defaultColor: '{{ constant('App\\Constants::DEFAULT_COLOR') }}',
},
{
'confirm': '{{ 'confirm'|trans }}',
'cancel': '{{ 'cancel'|trans }}',
'today': '{{ 'daterangepicker.today'|trans({}, 'daterangepicker')|escape('js') }}',
'yesterday': '{{ 'daterangepicker.yesterday'|trans({}, 'daterangepicker')|escape('js') }}',
'lastWeek': '{{ 'daterangepicker.lastWeek'|trans({}, 'daterangepicker')|escape('js') }}',
'thisWeek': '{{ 'daterangepicker.thisWeek'|trans({}, 'daterangepicker')|escape('js') }}',
'lastMonth': '{{ 'daterangepicker.lastMonth'|trans({}, 'daterangepicker')|escape('js') }}',
'thisMonth': '{{ 'daterangepicker.thisMonth'|trans({}, 'daterangepicker')|escape('js') }}',
'lastYear': '{{ 'daterangepicker.lastYear'|trans({}, 'daterangepicker')|escape('js') }}',
'thisYear': '{{ 'daterangepicker.thisYear'|trans({}, 'daterangepicker')|escape('js') }}',
'customRange': '{{ 'daterangepicker.customRange'|trans({}, 'daterangepicker')|escape('js') }}',
'timesheet.start.success': '{{ 'timesheet.start.success'|trans({}, 'flashmessages')|escape('js') }}',
'timesheet.start.error': '{{ 'timesheet.start.error'|trans({}, 'flashmessages')|escape('js') }}',
'timesheet.start.exceeded_limit': '{{ 'timesheet.start.exceeded_limit'|trans({}, 'flashmessages')|escape('js') }}',
'timesheet.stop.success': '{{ 'timesheet.stop.success'|trans({}, 'flashmessages')|escape('js') }}',
'timesheet.stop.error': '{{ 'timesheet.stop.error'|trans({}, 'flashmessages')|escape('js') }}',
'action.update.success': '{{ 'action.update.success'|trans({}, 'flashmessages')|escape('js') }}',
'action.update.error': '{{ 'action.update.error'|trans({}, 'flashmessages')|escape('js') }}',
'action.delete.success': '{{ 'action.delete.success'|trans({}, 'flashmessages')|escape('js') }}',
'action.delete.error': '{{ 'action.delete.error'|trans({}, 'flashmessages')|escape('js') }}',
'confirm.delete': '{{ 'confirm.delete'|trans|escape('js') }}',
'delete': '{{ 'action.delete'|trans|escape('js') }}',
'login.required': '{{ 'login_required'|trans|escape('js') }}'
{% for key, translation in javascript_translations() -%}
'{{ key }}': '{{ translation.0|trans({}, translation.1)|escape('js') }}',
{%- endfor %}
}
);
window.kimai = loader.getKimai();

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Tests\Event;
use App\Event\ThemeJavascriptTranslationsEvent;
use PHPUnit\Framework\TestCase;
/**
* @covers \App\Event\ThemeJavascriptTranslationsEvent
*/
class ThemeJavascriptTranslationsEventTest extends TestCase
{
public function testDefaultValues()
{
$sut = new ThemeJavascriptTranslationsEvent();
$this->assertCount(23, $sut->getTranslations());
}
public function testGetterAndSetter()
{
$sut = new ThemeJavascriptTranslationsEvent();
$sut->setTranslation('foo', 'bar');
$sut->setTranslation('hello', 'world', 'testing');
$result = $sut->getTranslations();
self::assertCount(25, $result);
self::assertArrayHasKey('foo', $result);
self::assertEquals(['bar', 'messages'], $result['foo']);
self::assertArrayHasKey('hello', $result);
self::assertEquals(['world', 'testing'], $result['hello']);
}
}

View File

@@ -25,7 +25,7 @@ class EventExtensionsTest extends TestCase
public function testGetFunctions()
{
$functions = ['trigger'];
$functions = ['trigger', 'javascript_translations'];
$sut = $this->getSut();
$twigFunctions = $sut->getFunctions();
self::assertCount(\count($functions), $twigFunctions);

View File

@@ -24,7 +24,7 @@ class ThemeEventExtensionTest extends TestCase
protected function getSut(bool $hasListener = true): ThemeEventExtension
{
$dispatcher = $this->createMock(EventDispatcherInterface::class);
$dispatcher->expects($this->once())->method('hasListeners')->willReturn($hasListener);
$dispatcher->method('hasListeners')->willReturn($hasListener);
$dispatcher->expects($hasListener ? $this->once() : $this->never())->method('dispatch');
$user = (new CurrentUserFactory($this))->create(new User());
@@ -45,4 +45,11 @@ class ThemeEventExtensionTest extends TestCase
$event = $sut->trigger('foo', []);
self::assertInstanceOf(ThemeEvent::class, $event);
}
public function testJavascriptTranslations()
{
$sut = $this->getSut();
$values = $sut->getJavascriptTranslations();
self::assertCount(23, $values);
}
}