Skip to content
This repository has been archived by the owner on Jan 30, 2020. It is now read-only.

Commit

Permalink
Merge branch 'feature/4187' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Show file tree
Hide file tree
Showing 2 changed files with 275 additions and 11 deletions.
159 changes: 148 additions & 11 deletions src/Translator/Translator.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
use Traversable;
use Zend\Cache;
use Zend\Cache\Storage\StorageInterface as CacheStorage;
use Zend\EventManager\EventManager;
use Zend\EventManager\EventManagerInterface;
use Zend\I18n\Exception;
use Zend\I18n\Translator\Loader\FileLoaderInterface;
use Zend\I18n\Translator\Loader\RemoteLoaderInterface;
Expand All @@ -23,6 +25,16 @@
*/
class Translator
{
/**
* Event fired when the translation for a message is missing.
*/
const EVENT_MISSING_TRANSLATION = 'missingTranslation';

/**
* Event fired when no messages were loaded for a locale/text-domain combination.
*/
const EVENT_NO_MESSAGES_LOADED = 'noMessagesLoaded';

/**
* Messages loaded by the translator.
*
Expand Down Expand Up @@ -79,6 +91,20 @@ class Translator
*/
protected $pluginManager;

/**
* Event manager for triggering translator events.
*
* @var EventManagerInterface
*/
protected $events;

/**
* Whether events are enabled
*
* @var bool
*/
protected $eventsEnabled = false;

/**
* Instantiate a translator
*
Expand Down Expand Up @@ -197,6 +223,11 @@ public static function factory($options)
}
}

// event manager enabled
if (isset($options['event_manager_enabled']) && $options['event_manager_enabled']) {
$translator->enableEventManager();
}

return $translator;
}

Expand Down Expand Up @@ -388,14 +419,15 @@ public function translatePlural(
/**
* Get a translated message.
*
* @param string $message
* @param string $locale
* @param string $textDomain
* @return string|null
* @triggers getTranslatedMessage.missing-translation
* @param string $message
* @param string $locale
* @param string $textDomain
* @return string|null
*/
protected function getTranslatedMessage(
$message,
$locale = null,
$locale,
$textDomain = 'default'
) {
if ($message === '') {
Expand All @@ -410,6 +442,25 @@ protected function getTranslatedMessage(
return $this->messages[$textDomain][$locale][$message];
}

if ($this->isEventManagerEnabled()) {
$results = $this->getEventManager()->trigger(
self::EVENT_MISSING_TRANSLATION,
$this,
array(
'message' => $message,
'locale' => $locale,
'text_domain' => $textDomain,
),
function ($r) {
return is_string($r);
}
);
$last = $results->last();
if (is_string($last)) {
return $last;
}
}

return null;
}

Expand Down Expand Up @@ -491,10 +542,11 @@ public function addRemoteTranslations($type, $textDomain = 'default')
/**
* Load messages for a given language and domain.
*
* @param string $textDomain
* @param string $locale
* @throws Exception\RuntimeException
* @return void
* @triggers loadMessages.no-messages-loaded
* @param string $textDomain
* @param string $locale
* @throws Exception\RuntimeException
* @return void
*/
protected function loadMessages($textDomain, $locale)
{
Expand All @@ -518,8 +570,30 @@ protected function loadMessages($textDomain, $locale)
$messagesLoaded |= $this->loadMessagesFromFiles($textDomain, $locale);

if (!$messagesLoaded) {
$this->messages[$textDomain][$locale] = null;
} elseif ($cache !== null) {
$discoveredTextDomain = null;
if ($this->isEventManagerEnabled()) {
$results = $this->getEventManager()->trigger(
self::EVENT_NO_MESSAGES_LOADED,
$this,
array(
'locale' => $locale,
'text_domain' => $textDomain,
),
function ($r) {
return ($r instanceof TextDomain);
}
);
$last = $results->last();
if ($last instanceof TextDomain) {
$discoveredTextDomain = $last;
}
}

$this->messages[$textDomain][$locale] = $discoveredTextDomain;
$messagesLoaded = true;
}

if ($messagesLoaded && $cache !== null) {
$cache->setItem($cacheId, $this->messages[$textDomain][$locale]);
}
}
Expand Down Expand Up @@ -632,4 +706,67 @@ protected function loadMessagesFromFiles($textDomain, $locale)

return $messagesLoaded;
}

/**
* Get the event manager.
*
* @return EventManagerInterface|null
*/
public function getEventManager()
{
if (!$this->events instanceof EventManagerInterface) {
$this->setEventManager(new EventManager());
}

return $this->events;
}

/**
* Set the event manager instance used by this translator.
*
* @param EventManagerInterface $events
* @return Translator
*/
public function setEventManager(EventManagerInterface $events)
{
$events->setIdentifiers(array(
__CLASS__,
get_class($this),
'translator',
));
$this->events = $events;
return $this;
}

/**
* Check whether the event manager is enabled.
*
* @return boolean
*/
public function isEventManagerEnabled()
{
return $this->eventsEnabled;
}

/**
* Enable the event manager.
*
* @return Translator
*/
public function enableEventManager()
{
$this->eventsEnabled = true;
return $this;
}

/**
* Disable the event manager.
*
* @return Translator
*/
public function disableEventManager()
{
$this->eventsEnabled = false;
return $this;
}
}
127 changes: 127 additions & 0 deletions test/Translator/TranslatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

use PHPUnit_Framework_TestCase as TestCase;
use Locale;
use Zend\EventManager\EventInterface;
use Zend\I18n\Translator\Translator;
use Zend\I18n\Translator\TextDomain;
use ZendTest\I18n\Translator\TestAsset\Loader as TestLoader;
Expand Down Expand Up @@ -234,4 +235,130 @@ public function testTranslateNonExistantLocale()
$this->assertEquals('Message 1', $this->translator->translate('Message 1'));
$this->assertEquals('Message 9', $this->translator->translate('Message 9'));
}

public function testEnableDisableEventManger()
{
$this->assertFalse($this->translator->isEventManagerEnabled(), 'Default value');

$this->translator->enableEventManager();
$this->assertTrue($this->translator->isEventManagerEnabled());

$this->translator->disableEventManager();
$this->assertFalse($this->translator->isEventManagerEnabled());
}

public function testEnableEventMangerViaFactory()
{
$translator = Translator::factory(array(
'event_manager_enabled' => true
));
$this->assertTrue($translator->isEventManagerEnabled());

$translator = Translator::factory(array());
$this->assertFalse($translator->isEventManagerEnabled());
}

public function testMissingTranslationEvent()
{
$actualEvent = null;

$this->translator->enableEventManager();
$this->translator->getEventManager()->attach(Translator::EVENT_MISSING_TRANSLATION, function(EventInterface $event) use (&$actualEvent) {
$actualEvent = $event;
});

$this->translator->translate('foo', 'bar', 'baz');

$this->assertInstanceOf('Zend\EventManager\Event', $actualEvent);
$this->assertEquals(
array(
'message' => 'foo',
'locale' => 'baz',
'text_domain' => 'bar',
),
$actualEvent->getParams()
);

// But fire no event when disabled
$actualEvent = null;
$this->translator->disableEventManager();
$this->translator->translate('foo', 'bar', 'baz');
$this->assertNull($actualEvent);
}

public function testListenerOnMissingTranslationEventCanReturnString()
{
$trigger = null;
$doNotTriger = null;

$this->translator->enableEventManager();
$this->translator->getEventManager()->attach(Translator::EVENT_MISSING_TRANSLATION, function(EventInterface $event) use (&$trigger) {
$trigger = true;
});
$this->translator->getEventManager()->attach(Translator::EVENT_MISSING_TRANSLATION, function(EventInterface $event) {
return 'EVENT TRIGGERED';
});
$this->translator->getEventManager()->attach(Translator::EVENT_MISSING_TRANSLATION, function(EventInterface $event) use (&$doNotTrigger) {
$doNotTrigger = true;
});

$result = $this->translator->translate('foo', 'bar', 'baz');
$this->assertTrue($trigger);
$this->assertEquals('EVENT TRIGGERED', $result);
$this->assertNull($doNotTrigger);
}

public function testNoMessagesLoadedEvent()
{
$actualEvent = null;

$this->translator->enableEventManager();
$this->translator->getEventManager()->attach(Translator::EVENT_NO_MESSAGES_LOADED, function(EventInterface $event) use (&$actualEvent) {
$actualEvent = $event;
});

$this->translator->translate('foo', 'bar', 'baz');

$this->assertInstanceOf('Zend\EventManager\Event', $actualEvent);
$this->assertEquals(
array(
'locale' => 'baz',
'text_domain' => 'bar',
),
$actualEvent->getParams()
);

// But fire no event when disabled
$actualEvent = null;
$this->translator->disableEventManager();
$this->translator->translate('foo', 'bar', 'baz');
$this->assertNull($actualEvent);
}

public function testListenerOnNoMessagesLoadedEventCanReturnTextDomainObject()
{
$trigger = null;
$doNotTrigger = null;
$textDomain = new TextDomain(array(
'foo' => 'BOOYAH',
));

$this->translator->enableEventManager();
$events = $this->translator->getEventManager();
$events->attach(Translator::EVENT_NO_MESSAGES_LOADED, function(EventInterface $event) use (&$trigger) {
$trigger = true;
});
$events->attach(Translator::EVENT_NO_MESSAGES_LOADED, function(EventInterface $event) use ($textDomain) {
return $textDomain;
});
$events->attach(Translator::EVENT_NO_MESSAGES_LOADED, function(EventInterface $event) use (&$doNotTrigger){
$doNotTrigger = true;
});

$result = $this->translator->translate('foo', 'bar', 'baz');

$this->assertTrue($trigger);
$this->assertNull($doNotTrigger);
$this->assertEquals('BOOYAH', $result);
}
}

0 comments on commit f592cc2

Please sign in to comment.