diff --git a/core/modules/locale/locale.post_update.php b/core/modules/locale/locale.post_update.php new file mode 100644 index 0000000000..91728f305e --- /dev/null +++ b/core/modules/locale/locale.post_update.php @@ -0,0 +1,13 @@ +storage[$offset] = $value; // Disabling the usage of string caching allows a module to watch for // the exact list of strings used on a page. From a performance diff --git a/core/modules/locale/tests/src/Functional/LocaleLocaleLookupTest.php b/core/modules/locale/tests/src/Functional/LocaleLocaleLookupTest.php index 5f3e5f7e80..0938895083 100644 --- a/core/modules/locale/tests/src/Functional/LocaleLocaleLookupTest.php +++ b/core/modules/locale/tests/src/Functional/LocaleLocaleLookupTest.php @@ -2,6 +2,7 @@ namespace Drupal\Tests\locale\Functional; +use Drupal\Core\StringTranslation\PluralTranslatableMarkup; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\Tests\BrowserTestBase; @@ -55,4 +56,46 @@ public function testLanguageFallbackDefaults() { $this->assertEqual($context['operation'], 'locale_lookup'); } + /** + * Test old plural style @count[number] fix. + * + * @dataProvider providerTestFixOldPluralStyle + */ + public function testFixOldPluralStyle($translation_value, $expected) { + /** @var \Drupal\locale\StringDatabaseStorage $string_storage */ + $string_storage = \Drupal::service('locale.storage'); + + $string = $string_storage->findString(['source' => 'Member for', 'context' => '']); + + // Create translation with old @count[2] plural style. + $string_storage->createTranslation([ + 'lid' => $string->getId(), + 'language' => 'fr', + 'translation' => $translation_value, + ])->save(); + + drupal_flush_all_caches(); + $this->drupalGet(''); + $this->assertSession()->pageTextContains($expected); + + // Assert that source not changed. + $translation = $string_storage->findTranslation(['language' => 'fr', 'lid' => $string->getId()])->translation; + $this->assertSame($translation_value, $translation); + } + + /** + * Provides data for testFixOldPluralStyle(). + * + * @return array + * An array of test data: + * - translation value + * - expected result + */ + public function providerTestFixOldPluralStyle() { + return [ + 'non-plural translation' => ['@count[2] non-plural test', '@count[2] non-plural test'], + 'plural translation' => ['@count[2] plural test' . PluralTranslatableMarkup::DELIMITER, '@count plural test'], + ]; + } + } diff --git a/core/modules/locale/tests/src/Unit/LocaleLookupTest.php b/core/modules/locale/tests/src/Unit/LocaleLookupTest.php index cbdd6deabb..42ecedb707 100644 --- a/core/modules/locale/tests/src/Unit/LocaleLookupTest.php +++ b/core/modules/locale/tests/src/Unit/LocaleLookupTest.php @@ -3,6 +3,7 @@ namespace Drupal\Tests\locale\Unit; use Drupal\Core\DependencyInjection\ContainerBuilder; +use Drupal\Core\StringTranslation\PluralTranslatableMarkup; use Drupal\locale\LocaleLookup; use Drupal\Tests\UnitTestCase; use Symfony\Component\HttpFoundation\Request; @@ -266,4 +267,66 @@ public function testResolveCacheMissNoTranslation() { $this->assertTrue($locale_lookup->get('test')); } + /** + * Tests locale lookups with old plural style of translations. + * + * @param array $translations + * The source with translations. + * @param string $langcode + * The language code of translation string. + * @param string $string + * The string for translation. + * @param bool $is_fix + * The flag about expected fix translation. + * + * @covers ::resolveCacheMiss + * @dataProvider providerFixOldPluralTranslationProvider + */ + public function testFixOldPluralStyleTranslations($translations, $langcode, $string, $is_fix) { + $this->storage->expects($this->any()) + ->method('findTranslation') + ->will($this->returnCallback(function ($argument) use ($translations) { + if (isset($translations[$argument['language']][$argument['source']])) { + return (object) ['translation' => $translations[$argument['language']][$argument['source']]]; + } + return TRUE; + })); + $this->languageManager->expects($this->any()) + ->method('getFallbackCandidates') + ->will($this->returnCallback(function (array $context = []) { + switch ($context['langcode']) { + case 'by': + return ['ru']; + } + })); + $this->cache->expects($this->once()) + ->method('get') + ->with('locale:' . $langcode . '::anonymous', FALSE); + + $locale_lookup = new LocaleLookup($langcode, '', $this->storage, $this->cache, $this->lock, $this->configFactory, $this->languageManager, $this->requestStack); + $this->assertSame($is_fix, strpos($locale_lookup->get($string), '@count[2]') === FALSE); + } + + /** + * Provides test data for testResolveCacheMissWithFallback(). + */ + public function providerFixOldPluralTranslationProvider() { + $translations = [ + 'by' => [ + 'word1' => '@count[2] word-by', + 'word2' => implode(PluralTranslatableMarkup::DELIMITER, ['word-by', '@count[2] word-by']), + ], + 'ru' => [ + 'word3' => '@count[2] word-ru', + 'word4' => implode(PluralTranslatableMarkup::DELIMITER, ['word-ru', '@count[2] word-ru']), + ], + ]; + return [ + 'no-plural' => [$translations, 'by', 'word1', FALSE], + 'no-plural from other language' => [$translations, 'by', 'word3', FALSE], + 'plural' => [$translations, 'by', 'word2', TRUE], + 'plural from other language' => [$translations, 'by', 'word4', TRUE], + ]; + } + }