Chris@0: storage = $this->getMock('Drupal\locale\StringStorageInterface'); Chris@0: $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface'); Chris@0: $this->lock = $this->getMock('Drupal\Core\Lock\LockBackendInterface'); Chris@0: $this->lock->expects($this->never()) Chris@0: ->method($this->anything()); Chris@0: Chris@0: $this->user = $this->getMock('Drupal\Core\Session\AccountInterface'); Chris@0: $this->user->expects($this->any()) Chris@0: ->method('getRoles') Chris@0: ->will($this->returnValue(['anonymous'])); Chris@0: Chris@0: $this->configFactory = $this->getConfigFactoryStub(['locale.settings' => ['cache_strings' => FALSE]]); Chris@0: Chris@0: $this->languageManager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface'); Chris@0: $this->requestStack = new RequestStack(); Chris@0: Chris@0: $container = new ContainerBuilder(); Chris@0: $container->set('current_user', $this->user); Chris@0: \Drupal::setContainer($container); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests locale lookups without fallback. Chris@0: * Chris@0: * @covers ::resolveCacheMiss Chris@0: */ Chris@0: public function testResolveCacheMissWithoutFallback() { Chris@0: $args = [ Chris@0: 'language' => 'en', Chris@0: 'source' => 'test', Chris@0: 'context' => 'irrelevant', Chris@0: ]; Chris@0: Chris@0: $result = (object) [ Chris@0: 'translation' => 'test', Chris@0: ]; Chris@0: Chris@0: $this->cache->expects($this->once()) Chris@0: ->method('get') Chris@0: ->with('locale:en:irrelevant:anonymous', FALSE); Chris@0: Chris@0: $this->storage->expects($this->once()) Chris@0: ->method('findTranslation') Chris@0: ->with($this->equalTo($args)) Chris@0: ->will($this->returnValue($result)); Chris@0: Chris@0: $locale_lookup = $this->getMockBuilder('Drupal\locale\LocaleLookup') Chris@0: ->setConstructorArgs(['en', 'irrelevant', $this->storage, $this->cache, $this->lock, $this->configFactory, $this->languageManager, $this->requestStack]) Chris@0: ->setMethods(['persist']) Chris@0: ->getMock(); Chris@0: $locale_lookup->expects($this->never()) Chris@0: ->method('persist'); Chris@0: $this->assertSame('test', $locale_lookup->get('test')); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests locale lookups with fallback. Chris@0: * Chris@0: * Note that context is irrelevant here. It is not used but it is required. Chris@0: * Chris@0: * @covers ::resolveCacheMiss Chris@0: * Chris@0: * @dataProvider resolveCacheMissWithFallbackProvider Chris@0: */ Chris@0: public function testResolveCacheMissWithFallback($langcode, $string, $context, $expected) { Chris@0: // These are fake words! Chris@0: $translations = [ Chris@0: 'en' => [ Chris@0: 'test' => 'test', Chris@0: 'fake' => 'fake', Chris@0: 'missing pl' => 'missing pl', Chris@0: 'missing cs' => 'missing cs', Chris@0: 'missing both' => 'missing both', Chris@0: ], Chris@0: 'pl' => [ Chris@0: 'test' => 'test po polsku', Chris@0: 'fake' => 'ściema', Chris@0: 'missing cs' => 'zaginiony czech', Chris@0: ], Chris@0: 'cs' => [ Chris@0: 'test' => 'test v české', Chris@0: 'fake' => 'falešný', Chris@0: 'missing pl' => 'chybějící pl', Chris@0: ], Chris@0: ]; Chris@0: $this->storage->expects($this->any()) Chris@0: ->method('findTranslation') Chris@0: ->will($this->returnCallback(function ($argument) use ($translations) { Chris@0: if (isset($translations[$argument['language']][$argument['source']])) { Chris@0: return (object) ['translation' => $translations[$argument['language']][$argument['source']]]; Chris@0: } Chris@0: return TRUE; Chris@0: })); Chris@0: Chris@0: $this->languageManager->expects($this->any()) Chris@0: ->method('getFallbackCandidates') Chris@0: ->will($this->returnCallback(function (array $context = []) { Chris@0: switch ($context['langcode']) { Chris@0: case 'pl': Chris@0: return ['cs', 'en']; Chris@0: Chris@0: case 'cs': Chris@0: return ['en']; Chris@0: Chris@0: default: Chris@0: return []; Chris@0: } Chris@0: })); Chris@0: Chris@0: $this->cache->expects($this->once()) Chris@0: ->method('get') Chris@0: ->with('locale:' . $langcode . ':' . $context . ':anonymous', FALSE); Chris@0: Chris@0: $locale_lookup = new LocaleLookup($langcode, $context, $this->storage, $this->cache, $this->lock, $this->configFactory, $this->languageManager, $this->requestStack); Chris@0: $this->assertSame($expected, $locale_lookup->get($string)); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Provides test data for testResolveCacheMissWithFallback(). Chris@0: */ Chris@0: public function resolveCacheMissWithFallbackProvider() { Chris@0: return [ Chris@0: ['cs', 'test', 'irrelevant', 'test v české'], Chris@0: ['cs', 'fake', 'irrelevant', 'falešný'], Chris@0: ['cs', 'missing pl', 'irrelevant', 'chybějící pl'], Chris@0: ['cs', 'missing cs', 'irrelevant', 'missing cs'], Chris@0: ['cs', 'missing both', 'irrelevant', 'missing both'], Chris@0: Chris@0: // Testing PL with fallback to cs, en. Chris@0: ['pl', 'test', 'irrelevant', 'test po polsku'], Chris@0: ['pl', 'fake', 'irrelevant', 'ściema'], Chris@0: ['pl', 'missing pl', 'irrelevant', 'chybějící pl'], Chris@0: ['pl', 'missing cs', 'irrelevant', 'zaginiony czech'], Chris@0: ['pl', 'missing both', 'irrelevant', 'missing both'], Chris@0: ]; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests locale lookups with persistent tracking. Chris@0: * Chris@0: * @covers ::resolveCacheMiss Chris@0: */ Chris@0: public function testResolveCacheMissWithPersist() { Chris@0: $args = [ Chris@0: 'language' => 'en', Chris@0: 'source' => 'test', Chris@0: 'context' => 'irrelevant', Chris@0: ]; Chris@0: Chris@0: $result = (object) [ Chris@0: 'translation' => 'test', Chris@0: ]; Chris@0: Chris@0: $this->storage->expects($this->once()) Chris@0: ->method('findTranslation') Chris@0: ->with($this->equalTo($args)) Chris@0: ->will($this->returnValue($result)); Chris@0: Chris@0: $this->configFactory = $this->getConfigFactoryStub(['locale.settings' => ['cache_strings' => TRUE]]); Chris@0: $locale_lookup = $this->getMockBuilder('Drupal\locale\LocaleLookup') Chris@0: ->setConstructorArgs(['en', 'irrelevant', $this->storage, $this->cache, $this->lock, $this->configFactory, $this->languageManager, $this->requestStack]) Chris@0: ->setMethods(['persist']) Chris@0: ->getMock(); Chris@0: $locale_lookup->expects($this->once()) Chris@0: ->method('persist'); Chris@0: Chris@0: $this->assertSame('test', $locale_lookup->get('test')); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests locale lookups without a found translation. Chris@0: * Chris@0: * @covers ::resolveCacheMiss Chris@0: */ Chris@0: public function testResolveCacheMissNoTranslation() { Chris@0: $string = $this->getMock('Drupal\locale\StringInterface'); Chris@0: $string->expects($this->once()) Chris@0: ->method('addLocation') Chris@0: ->will($this->returnSelf()); Chris@0: $this->storage->expects($this->once()) Chris@0: ->method('findTranslation') Chris@0: ->will($this->returnValue(NULL)); Chris@0: $this->storage->expects($this->once()) Chris@0: ->method('createString') Chris@0: ->will($this->returnValue($string)); Chris@0: Chris@0: $request = Request::create('/test'); Chris@0: $this->requestStack->push($request); Chris@0: Chris@0: $locale_lookup = $this->getMockBuilder('Drupal\locale\LocaleLookup') Chris@0: ->setConstructorArgs(['en', 'irrelevant', $this->storage, $this->cache, $this->lock, $this->configFactory, $this->languageManager, $this->requestStack]) Chris@0: ->setMethods(['persist']) Chris@0: ->getMock(); Chris@0: $locale_lookup->expects($this->never()) Chris@0: ->method('persist'); Chris@0: Chris@0: $this->assertTrue($locale_lookup->get('test')); Chris@0: } Chris@0: Chris@12: /** Chris@12: * Tests locale lookups with old plural style of translations. Chris@12: * Chris@12: * @param array $translations Chris@12: * The source with translations. Chris@12: * @param string $langcode Chris@12: * The language code of translation string. Chris@12: * @param string $string Chris@12: * The string for translation. Chris@12: * @param bool $is_fix Chris@12: * The flag about expected fix translation. Chris@12: * Chris@12: * @covers ::resolveCacheMiss Chris@12: * @dataProvider providerFixOldPluralTranslationProvider Chris@12: */ Chris@12: public function testFixOldPluralStyleTranslations($translations, $langcode, $string, $is_fix) { Chris@12: $this->storage->expects($this->any()) Chris@12: ->method('findTranslation') Chris@12: ->will($this->returnCallback(function ($argument) use ($translations) { Chris@12: if (isset($translations[$argument['language']][$argument['source']])) { Chris@12: return (object) ['translation' => $translations[$argument['language']][$argument['source']]]; Chris@12: } Chris@12: return TRUE; Chris@12: })); Chris@12: $this->languageManager->expects($this->any()) Chris@12: ->method('getFallbackCandidates') Chris@12: ->will($this->returnCallback(function (array $context = []) { Chris@12: switch ($context['langcode']) { Chris@12: case 'by': Chris@12: return ['ru']; Chris@12: } Chris@12: })); Chris@12: $this->cache->expects($this->once()) Chris@12: ->method('get') Chris@12: ->with('locale:' . $langcode . '::anonymous', FALSE); Chris@12: Chris@12: $locale_lookup = new LocaleLookup($langcode, '', $this->storage, $this->cache, $this->lock, $this->configFactory, $this->languageManager, $this->requestStack); Chris@12: $this->assertSame($is_fix, strpos($locale_lookup->get($string), '@count[2]') === FALSE); Chris@12: } Chris@12: Chris@12: /** Chris@12: * Provides test data for testResolveCacheMissWithFallback(). Chris@12: */ Chris@12: public function providerFixOldPluralTranslationProvider() { Chris@12: $translations = [ Chris@12: 'by' => [ Chris@12: 'word1' => '@count[2] word-by', Chris@18: 'word2' => implode(PoItem::DELIMITER, ['word-by', '@count[2] word-by']), Chris@12: ], Chris@12: 'ru' => [ Chris@12: 'word3' => '@count[2] word-ru', Chris@18: 'word4' => implode(PoItem::DELIMITER, ['word-ru', '@count[2] word-ru']), Chris@12: ], Chris@12: ]; Chris@12: return [ Chris@12: 'no-plural' => [$translations, 'by', 'word1', FALSE], Chris@12: 'no-plural from other language' => [$translations, 'by', 'word3', FALSE], Chris@12: 'plural' => [$translations, 'by', 'word2', TRUE], Chris@12: 'plural from other language' => [$translations, 'by', 'word4', TRUE], Chris@12: ]; Chris@12: } Chris@12: Chris@0: }