Chris@0: drupalCreateUser(['administer languages', 'access administration pages']); Chris@0: $this->drupalLogin($admin_user); Chris@0: Chris@0: $this->drupalPostForm('admin/config/regional/language/edit/en', ['locale_translate_english' => TRUE], t('Save language')); Chris@0: $this->assertLinkByHref('/admin/config/regional/translate?langcode=en', 0, 'Enabled interface translation to English.'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Adds a language and tests string translation by users with the appropriate permissions. Chris@0: */ Chris@0: public function testStringTranslation() { Chris@0: // User to add and remove language. Chris@0: $admin_user = $this->drupalCreateUser(['administer languages', 'access administration pages']); Chris@0: // User to translate and delete string. Chris@0: $translate_user = $this->drupalCreateUser(['translate interface', 'access administration pages']); Chris@0: // Code for the language. Chris@0: $langcode = 'xx'; Chris@0: // The English name for the language. This will be translated. Chris@0: $name = 'cucurbitaceae'; Chris@0: // This will be the translation of $name. Chris@0: $translation = $this->randomMachineName(16); Chris@0: $translation_to_en = $this->randomMachineName(16); Chris@0: Chris@0: // Add custom language. Chris@0: $this->drupalLogin($admin_user); Chris@0: $edit = [ Chris@0: 'predefined_langcode' => 'custom', Chris@0: 'langcode' => $langcode, Chris@0: 'label' => $name, Chris@0: 'direction' => LanguageInterface::DIRECTION_LTR, Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language')); Chris@0: // Add string. Chris@0: t($name, [], ['langcode' => $langcode])->render(); Chris@0: // Reset locale cache. Chris@0: $this->container->get('string_translation')->reset(); Chris@0: $this->assertRaw('"edit-languages-' . $langcode . '-weight"', 'Language code found.'); Chris@0: $this->assertText(t($name), 'Test language added.'); Chris@0: $this->drupalLogout(); Chris@0: Chris@0: // Search for the name and translate it. Chris@0: $this->drupalLogin($translate_user); Chris@0: $search = [ Chris@0: 'string' => $name, Chris@0: 'langcode' => $langcode, Chris@0: 'translation' => 'untranslated', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertText($name, 'Search found the string as untranslated.'); Chris@0: Chris@0: // No t() here, it's surely not translated yet. Chris@0: $this->assertText($name, 'name found on edit screen.'); Chris@0: $this->assertNoOption('edit-langcode', 'en', 'No way to translate the string to English.'); Chris@0: $this->drupalLogout(); Chris@0: $this->drupalLogin($admin_user); Chris@0: $this->drupalPostForm('admin/config/regional/language/edit/en', ['locale_translate_english' => TRUE], t('Save language')); Chris@0: $this->drupalLogout(); Chris@0: $this->drupalLogin($translate_user); Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertText($name, 'Search found the string as untranslated.'); Chris@0: Chris@0: // Assume this is the only result, given the random name. Chris@0: $textarea = current($this->xpath('//textarea')); Chris@0: $lid = $textarea->getAttribute('name'); Chris@0: $edit = [ Chris@0: $lid => $translation, Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations')); Chris@0: $this->assertText(t('The strings have been saved.'), 'The strings have been saved.'); Chris@0: $url_bits = explode('?', $this->getUrl()); Chris@18: $this->assertEqual($url_bits[0], Url::fromRoute('locale.translate_page', [], ['absolute' => TRUE])->toString(), 'Correct page redirection.'); Chris@0: $search = [ Chris@0: 'string' => $name, Chris@0: 'langcode' => $langcode, Chris@0: 'translation' => 'translated', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertRaw($translation, 'Non-English translation properly saved.'); Chris@0: Chris@0: $search = [ Chris@0: 'string' => $name, Chris@0: 'langcode' => 'en', Chris@0: 'translation' => 'untranslated', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $textarea = current($this->xpath('//textarea')); Chris@0: $lid = $textarea->getAttribute('name'); Chris@0: $edit = [ Chris@0: $lid => $translation_to_en, Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations')); Chris@0: $search = [ Chris@0: 'string' => $name, Chris@0: 'langcode' => 'en', Chris@0: 'translation' => 'translated', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertRaw($translation_to_en, 'English translation properly saved.'); Chris@0: Chris@0: $this->assertTrue($name != $translation && t($name, [], ['langcode' => $langcode]) == $translation, 't() works for non-English.'); Chris@0: // Refresh the locale() cache to get fresh data from t() below. We are in Chris@0: // the same HTTP request and therefore t() is not refreshed by saving the Chris@0: // translation above. Chris@0: $this->container->get('string_translation')->reset(); Chris@0: // Now we should get the proper fresh translation from t(). Chris@0: $this->assertTrue($name != $translation_to_en && t($name, [], ['langcode' => 'en']) == $translation_to_en, 't() works for English.'); Chris@0: $this->assertTrue(t($name, [], ['langcode' => LanguageInterface::LANGCODE_SYSTEM]) == $name, 't() works for LanguageInterface::LANGCODE_SYSTEM.'); Chris@0: Chris@0: $search = [ Chris@0: 'string' => $name, Chris@0: 'langcode' => 'en', Chris@0: 'translation' => 'untranslated', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertText(t('No strings available.'), 'String is translated.'); Chris@0: Chris@0: // Test invalidation of 'rendered' cache tag after string translation. Chris@0: $this->drupalLogout(); Chris@0: $this->drupalGet('xx/user/login'); Chris@0: $this->assertText('Enter the password that accompanies your username.'); Chris@0: Chris@0: $this->drupalLogin($translate_user); Chris@0: $search = [ Chris@0: 'string' => 'accompanies your username', Chris@0: 'langcode' => $langcode, Chris@0: 'translation' => 'untranslated', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $textarea = current($this->xpath('//textarea')); Chris@0: $lid = $textarea->getAttribute('name'); Chris@0: $edit = [ Chris@0: $lid => 'Please enter your Llama username.', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations')); Chris@0: Chris@0: $this->drupalLogout(); Chris@0: $this->drupalGet('xx/user/login'); Chris@0: $this->assertText('Please enter your Llama username.'); Chris@0: Chris@0: // Delete the language. Chris@0: $this->drupalLogin($admin_user); Chris@0: $path = 'admin/config/regional/language/delete/' . $langcode; Chris@0: // This a confirm form, we do not need any fields changed. Chris@0: $this->drupalPostForm($path, [], t('Delete')); Chris@0: // We need raw here because %language and %langcode will add HTML. Chris@0: $t_args = ['%language' => $name, '%langcode' => $langcode]; Chris@0: $this->assertRaw(t('The %language (%langcode) language has been removed.', $t_args), 'The test language has been removed.'); Chris@0: // Reload to remove $name. Chris@0: $this->drupalGet($path); Chris@0: // Verify that language is no longer found. Chris@0: $this->assertResponse(404, 'Language no longer found.'); Chris@0: $this->drupalLogout(); Chris@0: Chris@0: // Delete the string. Chris@0: $this->drupalLogin($translate_user); Chris@0: $search = [ Chris@0: 'string' => $name, Chris@0: 'langcode' => 'en', Chris@0: 'translation' => 'translated', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: // Assume this is the only result, given the random name. Chris@0: $textarea = current($this->xpath('//textarea')); Chris@0: $lid = $textarea->getAttribute('name'); Chris@0: $edit = [ Chris@0: $lid => '', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations')); Chris@0: $this->assertRaw($name, 'The strings have been saved.'); Chris@0: $this->drupalLogin($translate_user); Chris@0: $search = [ Chris@0: 'string' => $name, Chris@0: 'langcode' => 'en', Chris@0: 'translation' => 'untranslated', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertNoText(t('No strings available.'), 'The translation has been removed'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Adds a language and checks that the JavaScript translation files are Chris@0: * properly created and rebuilt on deletion. Chris@0: */ Chris@0: public function testJavaScriptTranslation() { Chris@0: $user = $this->drupalCreateUser(['translate interface', 'administer languages', 'access administration pages']); Chris@0: $this->drupalLogin($user); Chris@0: $config = $this->config('locale.settings'); Chris@0: Chris@0: $langcode = 'xx'; Chris@0: // The English name for the language. This will be translated. Chris@0: $name = $this->randomMachineName(16); Chris@0: Chris@0: // Add custom language. Chris@0: $edit = [ Chris@0: 'predefined_langcode' => 'custom', Chris@0: 'langcode' => $langcode, Chris@0: 'label' => $name, Chris@0: 'direction' => LanguageInterface::DIRECTION_LTR, Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language')); Chris@0: $this->container->get('language_manager')->reset(); Chris@0: Chris@0: // Build the JavaScript translation file. Chris@0: Chris@0: // Retrieve the source string of the first string available in the Chris@0: // {locales_source} table and translate it. Chris@18: $query = Database::getConnection()->select('locales_source', 's'); Chris@0: $query->addJoin('INNER', 'locales_location', 'l', 's.lid = l.lid'); Chris@0: $source = $query->fields('s', ['source']) Chris@0: ->condition('l.type', 'javascript') Chris@0: ->range(0, 1) Chris@0: ->execute() Chris@0: ->fetchField(); Chris@0: Chris@0: $search = [ Chris@0: 'string' => $source, Chris@0: 'langcode' => $langcode, Chris@0: 'translation' => 'all', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: Chris@0: $textarea = current($this->xpath('//textarea')); Chris@0: $lid = $textarea->getAttribute('name'); Chris@0: $edit = [ Chris@0: $lid => $this->randomMachineName(), Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations')); Chris@0: Chris@0: // Trigger JavaScript translation parsing and building. Chris@0: _locale_rebuild_js($langcode); Chris@0: Chris@0: $locale_javascripts = \Drupal::state()->get('locale.translation.javascript') ?: []; Chris@0: $js_file = 'public://' . $config->get('javascript.directory') . '/' . $langcode . '_' . $locale_javascripts[$langcode] . '.js'; Chris@17: $this->assertTrue($result = file_exists($js_file), new FormattableMarkup('JavaScript file created: %file', ['%file' => $result ? $js_file : 'not found'])); Chris@0: Chris@0: // Test JavaScript translation rebuilding. Chris@18: \Drupal::service('file_system')->delete($js_file); Chris@17: $this->assertTrue($result = !file_exists($js_file), new FormattableMarkup('JavaScript file deleted: %file', ['%file' => $result ? $js_file : 'found'])); Chris@0: _locale_rebuild_js($langcode); Chris@17: $this->assertTrue($result = file_exists($js_file), new FormattableMarkup('JavaScript file rebuilt: %file', ['%file' => $result ? $js_file : 'not found'])); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests the validation of the translation input. Chris@0: */ Chris@0: public function testStringValidation() { Chris@0: // User to add language and strings. Chris@0: $admin_user = $this->drupalCreateUser(['administer languages', 'access administration pages', 'translate interface']); Chris@0: $this->drupalLogin($admin_user); Chris@0: $langcode = 'xx'; Chris@0: // The English name for the language. This will be translated. Chris@0: $name = $this->randomMachineName(16); Chris@0: Chris@0: // These will be the invalid translations of $name. Chris@0: $key = $this->randomMachineName(16); Chris@0: $bad_translations[$key] = "" . $key; Chris@0: $key = $this->randomMachineName(16); Chris@0: $bad_translations[$key] = '' . $key; Chris@0: $key = $this->randomMachineName(16); Chris@0: $bad_translations[$key] = '<' . $key; Chris@0: $key = $this->randomMachineName(16); Chris@0: $bad_translations[$key] = "" . $key; Chris@0: Chris@0: // Add custom language. Chris@0: $edit = [ Chris@0: 'predefined_langcode' => 'custom', Chris@0: 'langcode' => $langcode, Chris@0: 'label' => $name, Chris@0: 'direction' => LanguageInterface::DIRECTION_LTR, Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language')); Chris@0: // Add string. Chris@0: t($name, [], ['langcode' => $langcode])->render(); Chris@0: // Reset locale cache. Chris@0: $search = [ Chris@0: 'string' => $name, Chris@0: 'langcode' => $langcode, Chris@0: 'translation' => 'all', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: // Find the edit path. Chris@0: Chris@0: $textarea = current($this->xpath('//textarea')); Chris@0: $lid = $textarea->getAttribute('name'); Chris@0: foreach ($bad_translations as $translation) { Chris@0: $edit = [ Chris@0: $lid => $translation, Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations')); Chris@0: // Check for a form error on the textarea. Chris@0: $form_class = $this->xpath('//form[@id="locale-translate-edit-form"]//textarea/@class'); Chris@0: $this->assertContains('error', $form_class[0]->getText(), 'The string was rejected as unsafe.'); Chris@0: $this->assertNoText(t('The string has been saved.'), 'The string was not saved.'); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests translation search form. Chris@0: */ Chris@0: public function testStringSearch() { Chris@0: // User to add and remove language. Chris@0: $admin_user = $this->drupalCreateUser(['administer languages', 'access administration pages']); Chris@0: // User to translate and delete string. Chris@0: $translate_user = $this->drupalCreateUser(['translate interface', 'access administration pages']); Chris@0: Chris@0: // Code for the language. Chris@0: $langcode = 'xx'; Chris@0: // The English name for the language. This will be translated. Chris@0: $name = $this->randomMachineName(16); Chris@0: // This will be the translation of $name. Chris@0: $translation = $this->randomMachineName(16); Chris@0: Chris@0: // Add custom language. Chris@0: $this->drupalLogin($admin_user); Chris@0: $edit = [ Chris@0: 'predefined_langcode' => 'custom', Chris@0: 'langcode' => $langcode, Chris@0: 'label' => $name, Chris@0: 'direction' => LanguageInterface::DIRECTION_LTR, Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language')); Chris@0: Chris@0: $edit = [ Chris@0: 'predefined_langcode' => 'custom', Chris@0: 'langcode' => 'yy', Chris@0: 'label' => $this->randomMachineName(16), Chris@0: 'direction' => LanguageInterface::DIRECTION_LTR, Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language')); Chris@0: Chris@0: // Add string. Chris@0: t($name, [], ['langcode' => $langcode])->render(); Chris@0: // Reset locale cache. Chris@0: $this->container->get('string_translation')->reset(); Chris@0: $this->drupalLogout(); Chris@0: Chris@0: // Search for the name. Chris@0: $this->drupalLogin($translate_user); Chris@0: $search = [ Chris@0: 'string' => $name, Chris@0: 'langcode' => $langcode, Chris@0: 'translation' => 'all', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: // assertText() seems to remove the input field where $name always could be Chris@0: // found, so this is not a false assert. See how assertNoText succeeds Chris@0: // later. Chris@0: $this->assertText($name, 'Search found the string.'); Chris@0: Chris@0: // Ensure untranslated string doesn't appear if searching on 'only Chris@0: // translated strings'. Chris@0: $search = [ Chris@0: 'string' => $name, Chris@0: 'langcode' => $langcode, Chris@0: 'translation' => 'translated', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertText(t('No strings available.'), "Search didn't find the string."); Chris@0: Chris@0: // Ensure untranslated string appears if searching on 'only untranslated Chris@0: // strings'. Chris@0: $search = [ Chris@0: 'string' => $name, Chris@0: 'langcode' => $langcode, Chris@0: 'translation' => 'untranslated', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertNoText(t('No strings available.'), 'Search found the string.'); Chris@0: Chris@0: // Add translation. Chris@0: // Assume this is the only result, given the random name. Chris@0: // We save the lid from the path. Chris@0: $textarea = current($this->xpath('//textarea')); Chris@0: $lid = $textarea->getAttribute('name'); Chris@0: $edit = [ Chris@0: $lid => $translation, Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations')); Chris@0: Chris@0: // Ensure translated string does appear if searching on 'only Chris@0: // translated strings'. Chris@0: $search = [ Chris@0: 'string' => $translation, Chris@0: 'langcode' => $langcode, Chris@0: 'translation' => 'translated', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertNoText(t('No strings available.'), 'Search found the translation.'); Chris@0: Chris@0: // Ensure translated source string doesn't appear if searching on 'only Chris@0: // untranslated strings'. Chris@0: $search = [ Chris@0: 'string' => $name, Chris@0: 'langcode' => $langcode, Chris@0: 'translation' => 'untranslated', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertText(t('No strings available.'), "Search didn't find the source string."); Chris@0: Chris@0: // Ensure translated string doesn't appear if searching on 'only Chris@0: // untranslated strings'. Chris@0: $search = [ Chris@0: 'string' => $translation, Chris@0: 'langcode' => $langcode, Chris@0: 'translation' => 'untranslated', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertText(t('No strings available.'), "Search didn't find the translation."); Chris@0: Chris@0: // Ensure translated string does appear if searching on the custom language. Chris@0: $search = [ Chris@0: 'string' => $translation, Chris@0: 'langcode' => $langcode, Chris@0: 'translation' => 'all', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertNoText(t('No strings available.'), 'Search found the translation.'); Chris@0: Chris@0: // Ensure translated string doesn't appear if searching in System (English). Chris@0: $search = [ Chris@0: 'string' => $translation, Chris@0: 'langcode' => 'yy', Chris@0: 'translation' => 'all', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertText(t('No strings available.'), "Search didn't find the translation."); Chris@0: Chris@0: // Search for a string that isn't in the system. Chris@0: $unavailable_string = $this->randomMachineName(16); Chris@0: $search = [ Chris@0: 'string' => $unavailable_string, Chris@0: 'langcode' => $langcode, Chris@0: 'translation' => 'all', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertText(t('No strings available.'), "Search didn't find the invalid string."); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests that only changed strings are saved customized when edited. Chris@0: */ Chris@0: public function testUICustomizedStrings() { Chris@0: $user = $this->drupalCreateUser(['translate interface', 'administer languages', 'access administration pages']); Chris@0: $this->drupalLogin($user); Chris@0: ConfigurableLanguage::createFromLangcode('de')->save(); Chris@0: Chris@0: // Create test source string. Chris@0: $string = $this->container->get('locale.storage')->createString([ Chris@0: 'source' => $this->randomMachineName(100), Chris@0: 'context' => $this->randomMachineName(20), Chris@0: ])->save(); Chris@0: Chris@0: // Create translation for new string and save it as non-customized. Chris@0: $translation = $this->container->get('locale.storage')->createTranslation([ Chris@0: 'lid' => $string->lid, Chris@0: 'language' => 'de', Chris@0: 'translation' => $this->randomMachineName(100), Chris@0: 'customized' => 0, Chris@0: ])->save(); Chris@0: Chris@0: // Reset locale cache. Chris@0: $this->container->get('string_translation')->reset(); Chris@0: Chris@0: // Ensure non-customized translation string does appear if searching Chris@0: // non-customized translation. Chris@0: $search = [ Chris@0: 'string' => $string->getString(), Chris@0: 'langcode' => 'de', Chris@0: 'translation' => 'translated', Chris@0: 'customized' => '0', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: Chris@0: $this->assertText($translation->getString(), 'Translation is found in search result.'); Chris@0: Chris@0: // Submit the translations without changing the translation. Chris@0: $textarea = current($this->xpath('//textarea')); Chris@0: $lid = $textarea->getAttribute('name'); Chris@0: $edit = [ Chris@0: $lid => $translation->getString(), Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations')); Chris@0: Chris@0: // Ensure unchanged translation string does appear if searching Chris@0: // non-customized translation. Chris@0: $search = [ Chris@0: 'string' => $string->getString(), Chris@0: 'langcode' => 'de', Chris@0: 'translation' => 'translated', Chris@0: 'customized' => '0', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertText($string->getString(), 'Translation is not marked as customized.'); Chris@0: Chris@0: // Submit the translations with a new translation. Chris@0: $textarea = current($this->xpath('//textarea')); Chris@0: $lid = $textarea->getAttribute('name'); Chris@0: $edit = [ Chris@0: $lid => $this->randomMachineName(100), Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations')); Chris@0: Chris@0: // Ensure changed translation string does appear if searching customized Chris@0: // translation. Chris@0: $search = [ Chris@0: 'string' => $string->getString(), Chris@0: 'langcode' => 'de', Chris@0: 'translation' => 'translated', Chris@0: 'customized' => '1', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); Chris@0: $this->assertText($string->getString(), "Translation is marked as customized."); Chris@0: } Chris@0: Chris@0: }