Chris@18: storage = $this->container->get('locale.storage'); Chris@18: // Create two languages: Spanish and German. Chris@18: foreach (['es', 'de'] as $langcode) { Chris@18: ConfigurableLanguage::createFromLangcode($langcode)->save(); Chris@18: } Chris@18: $this->installSchema('locale', [ Chris@18: 'locales_location', Chris@18: 'locales_source', Chris@18: 'locales_target', Chris@18: ]); Chris@18: } Chris@18: Chris@18: /** Chris@18: * Test CRUD API. Chris@18: */ Chris@18: public function testStringCrudApi() { Chris@18: // Create source string. Chris@18: $source = $this->buildSourceString()->save(); Chris@18: $this->assertTrue($source->lid); Chris@18: Chris@18: // Load strings by lid and source. Chris@18: $string1 = $this->storage->findString(['lid' => $source->lid]); Chris@18: $this->assertEquals($source, $string1); Chris@18: $string2 = $this->storage->findString(['source' => $source->source, 'context' => $source->context]); Chris@18: $this->assertEquals($source, $string2); Chris@18: $string3 = $this->storage->findString(['source' => $source->source, 'context' => '']); Chris@18: $this->assertFalse($string3); Chris@18: Chris@18: // Check version handling and updating. Chris@18: $this->assertEquals('none', $source->version); Chris@18: $string = $this->storage->findTranslation(['lid' => $source->lid]); Chris@18: $this->assertEquals(\Drupal::VERSION, $string->version); Chris@18: Chris@18: // Create translation and find it by lid and source. Chris@18: $langcode = 'es'; Chris@18: $translation = $this->createTranslation($source, $langcode); Chris@18: $this->assertEquals(LOCALE_NOT_CUSTOMIZED, $translation->customized); Chris@18: $string1 = $this->storage->findTranslation(['language' => $langcode, 'lid' => $source->lid]); Chris@18: $this->assertEquals($translation->translation, $string1->translation); Chris@18: $string2 = $this->storage->findTranslation(['language' => $langcode, 'source' => $source->source, 'context' => $source->context]); Chris@18: $this->assertEquals($translation->translation, $string2->translation); Chris@18: $translation Chris@18: ->setCustomized() Chris@18: ->save(); Chris@18: $translation = $this->storage->findTranslation(['language' => $langcode, 'lid' => $source->lid]); Chris@18: $this->assertEquals(LOCALE_CUSTOMIZED, $translation->customized); Chris@18: Chris@18: // Delete translation. Chris@18: $translation->delete(); Chris@18: $deleted = $this->storage->findTranslation(['language' => $langcode, 'lid' => $source->lid]); Chris@18: $this->assertNull($deleted->translation); Chris@18: Chris@18: // Create some translations and then delete string and all of its Chris@18: // translations. Chris@18: $lid = $source->lid; Chris@18: $this->createAllTranslations($source); Chris@18: $search = $this->storage->getTranslations(['lid' => $source->lid]); Chris@18: $this->assertCount(3, $search); Chris@18: Chris@18: $source->delete(); Chris@18: $string = $this->storage->findString(['lid' => $lid]); Chris@18: $this->assertFalse($string); Chris@18: $deleted = $search = $this->storage->getTranslations(['lid' => $lid]); Chris@18: $this->assertFalse($deleted); Chris@18: Chris@18: // Tests that locations of different types and arbitrary lengths can be Chris@18: // added to a source string. Too long locations will be cut off. Chris@18: $source_string = $this->buildSourceString(); Chris@18: $source_string->addLocation('javascript', $this->randomString(8)); Chris@18: $source_string->addLocation('configuration', $this->randomString(50)); Chris@18: $source_string->addLocation('code', $this->randomString(100)); Chris@18: $source_string->addLocation('path', $location = $this->randomString(300)); Chris@18: $source_string->save(); Chris@18: Chris@18: $rows = $this->container->get('database')->select('locales_location') Chris@18: ->fields('locales_location') Chris@18: ->condition('sid', $source_string->lid) Chris@18: ->execute() Chris@18: ->fetchAllAssoc('type'); Chris@18: $this->assertCount(4, $rows); Chris@18: $this->assertEquals(substr($location, 0, 255), $rows['path']->name); Chris@18: } Chris@18: Chris@18: /** Chris@18: * Test Search API loading multiple objects. Chris@18: */ Chris@18: public function testStringSearchApi() { Chris@18: $language_count = 3; Chris@18: // Strings 1 and 2 will have some common prefix. Chris@18: // Source 1 will have all translations, not customized. Chris@18: // Source 2 will have all translations, customized. Chris@18: // Source 3 will have no translations. Chris@18: $prefix = $this->randomMachineName(100); Chris@18: $source1 = $this->buildSourceString(['source' => $prefix . $this->randomMachineName(100)])->save(); Chris@18: $source2 = $this->buildSourceString(['source' => $prefix . $this->randomMachineName(100)])->save(); Chris@18: $source3 = $this->buildSourceString()->save(); Chris@18: Chris@18: // Load all source strings. Chris@18: $strings = $this->storage->getStrings([]); Chris@18: $this->assertCount(3, $strings); Chris@18: // Load all source strings matching a given string. Chris@18: $filter_options['filters'] = ['source' => $prefix]; Chris@18: $strings = $this->storage->getStrings([], $filter_options); Chris@18: $this->assertCount(2, $strings); Chris@18: Chris@18: // Not customized translations. Chris@18: $translate1 = $this->createAllTranslations($source1); Chris@18: // Customized translations. Chris@18: $this->createAllTranslations($source2, ['customized' => LOCALE_CUSTOMIZED]); Chris@18: // Try quick search function with different field combinations. Chris@18: $langcode = 'es'; Chris@18: $found = $this->storage->findTranslation(['language' => $langcode, 'source' => $source1->source, 'context' => $source1->context]); Chris@18: $this->assertTrue($found && isset($found->language) && isset($found->translation) && !$found->isNew(), 'Translation not found searching by source and context.'); Chris@18: $this->assertEquals($translate1[$langcode]->translation, $found->translation); Chris@18: // Now try a translation not found. Chris@18: $found = $this->storage->findTranslation(['language' => $langcode, 'source' => $source3->source, 'context' => $source3->context]); Chris@18: $this->assertTrue($found && $found->lid == $source3->lid && !isset($found->translation) && $found->isNew()); Chris@18: Chris@18: // Load all translations. For next queries we'll be loading only translated Chris@18: // strings. Chris@18: $translations = $this->storage->getTranslations(['translated' => TRUE]); Chris@18: $this->assertCount(2 * $language_count, $translations); Chris@18: Chris@18: // Load all customized translations. Chris@18: $translations = $this->storage->getTranslations(['customized' => LOCALE_CUSTOMIZED, 'translated' => TRUE]); Chris@18: $this->assertCount($language_count, $translations); Chris@18: Chris@18: // Load all Spanish customized translations. Chris@18: $translations = $this->storage->getTranslations(['language' => 'es', 'customized' => LOCALE_CUSTOMIZED, 'translated' => TRUE]); Chris@18: $this->assertCount(1, $translations); Chris@18: Chris@18: // Load all source strings without translation (1). Chris@18: $translations = $this->storage->getStrings(['translated' => FALSE]); Chris@18: $this->assertCount(1, $translations); Chris@18: Chris@18: // Load Spanish translations using string filter. Chris@18: $filter_options['filters'] = ['source' => $prefix]; Chris@18: $translations = $this->storage->getTranslations(['language' => 'es'], $filter_options); Chris@18: $this->assertCount(2, $translations); Chris@18: } Chris@18: Chris@18: /** Chris@18: * Creates random source string object. Chris@18: * Chris@18: * @param array $values Chris@18: * The values array. Chris@18: * Chris@18: * @return \Drupal\locale\StringInterface Chris@18: * A locale string. Chris@18: */ Chris@18: protected function buildSourceString(array $values = []) { Chris@18: return $this->storage->createString($values += [ Chris@18: 'source' => $this->randomMachineName(100), Chris@18: 'context' => $this->randomMachineName(20), Chris@18: ]); Chris@18: } Chris@18: Chris@18: /** Chris@18: * Creates translations for source string and all languages. Chris@18: * Chris@18: * @param \Drupal\locale\StringInterface $source Chris@18: * The source string. Chris@18: * @param array $values Chris@18: * The values array. Chris@18: * Chris@18: * @return array Chris@18: * Translation list. Chris@18: */ Chris@18: protected function createAllTranslations(StringInterface $source, array $values = []) { Chris@18: $list = []; Chris@18: /* @var $language_manager \Drupal\Core\Language\LanguageManagerInterface */ Chris@18: $language_manager = $this->container->get('language_manager'); Chris@18: foreach ($language_manager->getLanguages() as $language) { Chris@18: $list[$language->getId()] = $this->createTranslation($source, $language->getId(), $values); Chris@18: } Chris@18: return $list; Chris@18: } Chris@18: Chris@18: /** Chris@18: * Creates single translation for source string. Chris@18: * Chris@18: * @param \Drupal\locale\StringInterface $source Chris@18: * The source string. Chris@18: * @param string $langcode Chris@18: * The language code. Chris@18: * @param array $values Chris@18: * The values array. Chris@18: * Chris@18: * @return \Drupal\locale\StringInterface Chris@18: * The translated string object. Chris@18: */ Chris@18: protected function createTranslation(StringInterface $source, $langcode, array $values = []) { Chris@18: return $this->storage->createTranslation($values + [ Chris@18: 'lid' => $source->lid, Chris@18: 'language' => $langcode, Chris@18: 'translation' => $this->randomMachineName(100), Chris@18: ])->save(); Chris@18: } Chris@18: Chris@18: }