diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationFormBase.php b/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationFormBase.php index 8d60281..462e1b7 100644 --- a/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationFormBase.php +++ b/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationFormBase.php @@ -230,7 +230,7 @@ public function submitForm(array &$form, array &$form_state) { $config_translation = $this->languageManager->getLanguageConfigOverride($this->language->id, $name); $locations = $this->localeStorage->getLocations(array('type' => 'configuration', 'name' => $name)); - $this->setConfig($this->language, $base_config, $config_translation, $form_values[$name], $this->typedConfigManager->get($name), !empty($locations)); + $this->setConfig($this->language, $base_config, $config_translation, $this->typedConfigManager->get($name), $form_values[$name], !empty($locations)); // If no overrides, delete language specific configuration file. $saved_config = $config_translation->get(); @@ -287,6 +287,13 @@ protected function buildConfigForm($name, Element $schema, $config_data, $base_c $this->moduleHandler->alter('config_translation_type_info', $definitions); $element_type = $definition['type']; + // When building the form we traverse the schema until we find an element + // with a form element class. When setting the config values in, we + // instead traverse the schema until we find a translatable element. This + // allows for for elements handling multiple schema parts only some of + // which are translatable. The TextFormat element requires this as the + // form inherently covers the 'format' property as well, even though that + // is not translatable. if ($element instanceof Element && !isset($definitions[$element_type]['form_element_class'])) { // Build sub-structure and include it with a wrapper in the form // if there are any translatable elements there. @@ -320,11 +327,15 @@ protected function buildConfigForm($name, Element $schema, $config_data, $base_c } } elseif (isset($definition['form_element_class'])) { + /** @var \Drupal\config_translation\FormElement\ElementInterface $form_element */ + $form_element = new $definition['form_element_class'](); + $value = $config_data[$key]; $build[$element_key] = array( '#theme' => 'config_translation_manage_form_element', ); $build[$element_key]['source'] = array( + '#markup' => $form_element->getRenderedSource($base_config_data[$key], $this->sourceLanguage), '#title' => $this->t( '!label (!source_language)', array( @@ -333,14 +344,21 @@ protected function buildConfigForm($name, Element $schema, $config_data, $base_c ) ), '#type' => 'item', + // The 'item' element generally receives input, but in this case it is + // both unnecessary and unwanted, as we only want one form value per + // configuration element. + // @see system_element_info() '#input' => FALSE, ); - /** @var \Drupal\config_translation\FormElement\ElementInterface $form_element */ - $form_element = new $definition['form_element_class'](); - - $build[$element_key]['source']['#markup'] = $form_element->getRenderedSource($base_config_data, $key, $this->sourceLanguage, $this->language); $build[$element_key]['translation'] = $form_element->getFormElement($definition, $this->language, $value); + // For accessibility we make source and translation appear next to each + // other in the source for each element, which is why we utilize the + // 'source' and 'translation' sub-keys for the form. The form values, + // however, should mirror the configuration structure, so that we can + // traverse the configuration schema in + // ConfigTranslationFormBase::setConfig(). Therefore, the 'translation' + // key is removed from the form parents. $build[$element_key]['translation']['#parents'] = array_merge(array('config_names', $name), explode('.', $element_key)); } } @@ -356,6 +374,8 @@ protected function buildConfigForm($name, Element $schema, $config_data, $base_c * Base configuration values, in the source language. * @param \Drupal\Core\Config\Config $config_translation * Translation configuration override data. + * @param \Drupal\Core\Config\Schema\Element $schema + * Schema definition of configuration. * @param array $config_values * A simple one dimensional or recursive array: * - simple: @@ -367,26 +387,30 @@ protected function buildConfigForm($name, Element $schema, $config_data, $base_c * ); * Either format is used, the nested arrays are just containers and not * needed for saving the data. - * @param \Drupal\Core\Config\Schema\Element $schema - * Schema definition of configuration. * @param bool $shipped_config * (optional) Flag to specify whether the configuration had a shipped * version and therefore should also be stored in the locale database. * + * @param null $base_key * @return array * Translation configuration override data. */ - protected function setConfig(Language $language, Config $base_config, Config $config_translation, array $config_values, Element $schema, $shipped_config = FALSE, $base_key = NULL) { + protected function setConfig(Language $language, Config $base_config, Config $config_translation, Element $schema, array $config_values, $shipped_config = FALSE, $base_key = NULL) { foreach ($schema as $key => $element) { if (!isset($config_values[$key])) { continue; } + $value = $config_values[$key]; + $element_key = implode('.', array_filter(array($base_key, $key))); $definition = $element->getDataDefinition(); - $value = $config_values[$key]; + // While the 'form_element_class' key is used for form building, the + // 'translatable' key is used for the setting of configuration values. + // This allows the form to contain values which will not be set, such as + // the TextFormat element's 'format' value. if ($element instanceof Element && empty($definition['translatable'])) { // Traverse into this level in the configuration. - $this->setConfig($language, $base_config, $config_translation, $value, $element, $shipped_config, $element_key); + $this->setConfig($language, $base_config, $config_translation, $element, $value, $shipped_config, $element_key); } else { // If the configuration file being translated was originally shipped, we @@ -403,40 +427,10 @@ protected function setConfig(Language $language, Config $base_config, Config $co // If we got a translation, take that, otherwise create a new one. $translation = reset($translations) ?: $this->localeStorage->createTranslation($conditions); - // Some schema types provide a form_element_class which is responsible - // for providing us with a translation string. We iterate through the - // $key string to check if we have a schema definition for that. - $types = explode(".", $key); - $type = array_shift($types); - // If there is a schema definition, run the - // hook_config_translation_type_info_alter. - if (isset($schema[$type])) { - $element = $schema[$type]; - $definition = $element->getDataDefinition(); - - // Invoke hook_config_translation_type_info_alter() implementations to - // alter the configuration types. - $definitions = array( - $definition['type'] => &$definition, - ); - $this->moduleHandler->alter('config_translation_type_info', $definitions); - } - - // If form_element_class is set, create a new object of this class and - // let it return the string of the translation. - if (isset($definition['form_element_class'])) { - /** @var \Drupal\config_translation\FormElement\ElementInterface $form_element */ - $form_element = new $definition['form_element_class'](); - - $translation_string = $form_element->getTranslationString($value); - } else { - $translation_string = $value; - } - // If we have a new translation or different from what is stored in // locale before, save this as an updated customize translation. - if ($translation->isNew() || $translation->getString() != $translation_string) { - $translation->setString($translation_string) + if ($translation->isNew() || $translation->getString() != $value) { + $translation->setString($value) ->setCustomized() ->save(); } diff --git a/core/modules/config_translation/lib/Drupal/config_translation/FormElement/Element.php b/core/modules/config_translation/lib/Drupal/config_translation/FormElement/Element.php index ce33fcb..6c83332 100644 --- a/core/modules/config_translation/lib/Drupal/config_translation/FormElement/Element.php +++ b/core/modules/config_translation/lib/Drupal/config_translation/FormElement/Element.php @@ -46,15 +46,8 @@ protected function translationManager() { /** * {@inheritdoc} */ - public function getRenderedSource($base_config_data, $key, Language $source_language, Language $language) { - return $base_config_data[$key] ? ('' . nl2br($base_config_data[$key] . '')) : t('(Empty)'); - } - - /** - * {@inheritdoc} - */ - public function getTranslationString($value) { - return $value; + public function getRenderedSource($base_config, Language $source_language) { + return $base_config ? ('' . nl2br($base_config . '')) : t('(Empty)'); } } diff --git a/core/modules/config_translation/lib/Drupal/config_translation/FormElement/ElementInterface.php b/core/modules/config_translation/lib/Drupal/config_translation/FormElement/ElementInterface.php index 3713024..188d02d 100644 --- a/core/modules/config_translation/lib/Drupal/config_translation/FormElement/ElementInterface.php +++ b/core/modules/config_translation/lib/Drupal/config_translation/FormElement/ElementInterface.php @@ -32,31 +32,14 @@ public function getFormElement(array $definition, Language $language, $value); /** * Returns the rendered source element for a given configuration definition. * - * @param array|string $base_config_data - * Configuration object of base language, a string when done traversing - * the data building each sub-structure for the form. - * @param string $key - * The key in the configuration object. + * @param array|string $base_config + * The configuration value of the element in the source language. * @param \Drupal\Core\Language\Language $source_language * Thee source language of the configuration object. - * @param \Drupal\Core\Language\Language $language - * Language object to display the translation form for. * * @return string * The rendered value in source language. */ - public function getRenderedSource($base_config_data, $key, Language $source_language, Language $language); - - - /** - * Returns the translation to be used in string storage. - * - * @param mixed $value - * The value of the translation element. - * - * @return string - * String of translation. - */ - public function getTranslationString($value); + public function getRenderedSource($base_config, Language $source_language); } diff --git a/core/modules/config_translation/lib/Drupal/config_translation/FormElement/TextFormat.php b/core/modules/config_translation/lib/Drupal/config_translation/FormElement/TextFormat.php index 522dbda..9be98d2 100644 --- a/core/modules/config_translation/lib/Drupal/config_translation/FormElement/TextFormat.php +++ b/core/modules/config_translation/lib/Drupal/config_translation/FormElement/TextFormat.php @@ -31,16 +31,9 @@ public function getFormElement(array $definition, Language $language, $value) { /** * {@inheritdoc} */ - public function getRenderedSource($base_config_data, $key, Language $source_language, Language $language) { - $value = check_markup($base_config_data[$key]['value'], $base_config_data[$key]['format'], $source_language->id); + public function getRenderedSource($base_config, Language $source_language) { + $value = check_markup($base_config['value'], $base_config['format'], $source_language->id); return $value ? '' . $value . '' : t('(Empty)'); } - /** - * {@inheritdoc} - */ - public function getTranslationString($value) { - return $value['value']; - } - } diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php b/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php index 12fd5a5..16f4d20 100644 --- a/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php +++ b/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php @@ -127,8 +127,8 @@ public function testSiteInformationTranslationUi() { // Update site name and slogan for French. $edit = array( - 'config_names[system.site][name][translation]' => $fr_site_name, - 'config_names[system.site][slogan][translation]' => $fr_site_slogan, + 'config_names[system.site][name]' => $fr_site_name, + 'config_names[system.site][slogan]' => $fr_site_slogan, ); $this->drupalPostForm("$translation_base_url/fr/add", $edit, t('Save translation')); @@ -141,8 +141,8 @@ public function testSiteInformationTranslationUi() { // Check translation saved proper. $this->drupalGet("$translation_base_url/fr/edit"); - $this->assertFieldByName('config_names[system.site][name][translation]', $fr_site_name); - $this->assertFieldByName('config_names[system.site][slogan][translation]', $fr_site_slogan); + $this->assertFieldByName('config_names[system.site][name]', $fr_site_name); + $this->assertFieldByName('config_names[system.site][slogan]', $fr_site_slogan); // Check French translation of site name and slogan are in place. $this->drupalGet('fr'); @@ -170,8 +170,8 @@ public function testSourceValueDuplicateSave() { // Case 1: Update new value for site slogan and site name. $edit = array( - 'config_names[system.site][name][translation]' => 'FR ' . $site_name, - 'config_names[system.site][slogan][translation]' => 'FR ' . $site_slogan, + 'config_names[system.site][name]' => 'FR ' . $site_name, + 'config_names[system.site][slogan]' => 'FR ' . $site_slogan, ); // First time, no overrides, so just Add link. $this->drupalPostForm("$translation_base_url/fr/add", $edit, t('Save translation')); @@ -193,8 +193,8 @@ public function testSourceValueDuplicateSave() { $this->assertNoText('FR ' . $site_name); $this->assertNoText('FR ' . $site_slogan); $edit = array( - 'config_names[system.site][name][translation]' => $site_name, - 'config_names[system.site][slogan][translation]' => 'FR ' . $site_slogan, + 'config_names[system.site][name]' => $site_name, + 'config_names[system.site][slogan]' => 'FR ' . $site_slogan, ); $this->drupalPostForm(NULL, $edit, t('Save translation')); $this->assertRaw(t('Successfully updated @language translation.', array('@language' => 'French'))); @@ -208,8 +208,8 @@ public function testSourceValueDuplicateSave() { $this->drupalGet("$translation_base_url/fr/edit"); $this->assertNoText('FR ' . $site_slogan); $edit = array( - 'config_names[system.site][name][translation]' => $site_name, - 'config_names[system.site][slogan][translation]' => $site_slogan, + 'config_names[system.site][name]' => $site_name, + 'config_names[system.site][slogan]' => $site_slogan, ); $this->drupalPostForm(NULL, $edit, t('Save translation')); $override = \Drupal::languageManager()->getLanguageConfigOverride('fr', 'system.site'); @@ -273,8 +273,8 @@ public function testContactConfigEntityTranslation() { // Update translatable fields. $edit = array( - 'config_names[contact.category.feedback][label][translation]' => 'Website feedback - ' . $langcode, - 'config_names[contact.category.feedback][reply][translation]' => 'Thank you for your mail - ' . $langcode, + 'config_names[contact.category.feedback][label]' => 'Website feedback - ' . $langcode, + 'config_names[contact.category.feedback][reply]' => 'Thank you for your mail - ' . $langcode, ); // Save language specific version of form. @@ -312,7 +312,7 @@ public function testContactConfigEntityTranslation() { $langcode_prefixes = array_merge(array(''), $this->langcodes); foreach ($langcode_prefixes as $langcode_prefix) { $this->drupalGet(ltrim("$langcode_prefix/$translation_base_url/$langcode/edit")); - $this->assertFieldByName('config_names[contact.category.feedback][label][translation]', 'Website feedback - ' . $langcode); + $this->assertFieldByName('config_names[contact.category.feedback][label]', 'Website feedback - ' . $langcode); $this->assertText($label); } } @@ -402,8 +402,8 @@ public function testDateFormatTranslation() { // Update translatable fields. $edit = array( - 'config_names[system.date_format.' . $id . '][label][translation]' => $id . ' - FR', - 'config_names[system.date_format.' . $id . '][pattern][pattern.php][translation]' => 'D', + 'config_names[system.date_format.' . $id . '][label]' => $id . ' - FR', + 'config_names[system.date_format.' . $id . '][pattern][php]' => 'D', ); // Save language specific version of form. @@ -439,9 +439,9 @@ public function testAccountSettingsConfigurationTranslation() { // Update account settings fields for French. $edit = array( - 'config_names[user.settings][anonymous][translation]' => 'Anonyme', - 'config_names[user.mail][status_blocked][status_blocked.subject][translation]' => 'Testing, your account is blocked.', - 'config_names[user.mail][status_blocked][status_blocked.body][translation]' => 'Testing account blocked body.', + 'config_names[user.settings][anonymous]' => 'Anonyme', + 'config_names[user.mail][status_blocked][subject]' => 'Testing, your account is blocked.', + 'config_names[user.mail][status_blocked][body]' => 'Testing account blocked body.', ); $this->drupalPostForm('admin/config/people/accounts/translate/fr/add', $edit, t('Save translation')); @@ -450,7 +450,7 @@ public function testAccountSettingsConfigurationTranslation() { $this->drupalGet('admin/config/people/accounts/translate/fr/edit'); foreach ($edit as $key => $value) { // Check the translations appear in the right field type as well. - $xpath = '//' . (strpos($key, '.body') ? 'textarea' : 'input') . '[@name="'. $key . '"]'; + $xpath = '//' . (strpos($key, '[body]') ? 'textarea' : 'input') . '[@name="'. $key . '"]'; $this->assertFieldByXPath($xpath, $value); } // Check that labels for email settings appear. @@ -537,10 +537,10 @@ public function testViewsTranslationUI() { // Update Views Fields for French. $edit = array( - 'config_names[views.view.frontpage][description][translation]' => $description . " FR", - 'config_names[views.view.frontpage][label][translation]' => $human_readable_name . " FR", - 'config_names[views.view.frontpage][display][default][display.default.display_title][translation]' => $display_settings_master . " FR", - 'config_names[views.view.frontpage][display][default][display_options][display.default.display_options.title][translation]' => $display_options_master . " FR", + 'config_names[views.view.frontpage][description]' => $description . " FR", + 'config_names[views.view.frontpage][label]' => $human_readable_name . " FR", + 'config_names[views.view.frontpage][display][default][display_title]' => $display_settings_master . " FR", + 'config_names[views.view.frontpage][display][default][display_options][title]' => $display_options_master . " FR", ); $this->drupalPostForm("$translation_base_url/fr/add", $edit, t('Save translation')); $this->assertRaw(t('Successfully saved @language translation.', array('@language' => 'French'))); @@ -552,10 +552,10 @@ public function testViewsTranslationUI() { // Check translation saved proper. $this->drupalGet("$translation_base_url/fr/edit"); - $this->assertFieldByName('config_names[views.view.frontpage][description][translation]', $description . " FR"); - $this->assertFieldByName('config_names[views.view.frontpage][label][translation]', $human_readable_name . " FR"); - $this->assertFieldByName('config_names[views.view.frontpage][display][default][display.default.display_title][translation]', $display_settings_master . " FR"); - $this->assertFieldByName('config_names[views.view.frontpage][display][default][display_options][display.default.display_options.title][translation]', $display_options_master . " FR"); + $this->assertFieldByName('config_names[views.view.frontpage][description]', $description . " FR"); + $this->assertFieldByName('config_names[views.view.frontpage][label]', $human_readable_name . " FR"); + $this->assertFieldByName('config_names[views.view.frontpage][display][default][display_title]', $display_settings_master . " FR"); + $this->assertFieldByName('config_names[views.view.frontpage][display][default][display_options][title]', $display_options_master . " FR"); } /** @@ -586,7 +586,7 @@ public function testLocaleDBStorage() { // Add custom translation. $edit = array( - 'config_names[user.settings][anonymous][translation]' => 'Anonyme', + 'config_names[user.settings][anonymous]' => 'Anonyme', ); $this->drupalPostForm('admin/config/people/accounts/translate/fr/add', $edit, t('Save translation')); @@ -597,7 +597,7 @@ public function testLocaleDBStorage() { // revert custom translations to base translation. $edit = array( - 'config_names[user.settings][anonymous][translation]' => 'Anonymous', + 'config_names[user.settings][anonymous]' => 'Anonymous', ); $this->drupalPostForm('admin/config/people/accounts/translate/fr/edit', $edit, t('Save translation')); @@ -678,23 +678,18 @@ public function testThemeDiscovery() { */ public function testTextFormatTranslation() { $this->drupalLogin($this->admin_user); - $file_storage = new FileStorage($this->configDirectories[CONFIG_ACTIVE_DIRECTORY]); - - $config_parsed = $file_storage->read('config_translation_test.content'); - $config_parsed_compare = array( - 'content' => array( - 'value' => $config_parsed['content']['value'], - 'format' => $config_parsed['content']['format'], - ), - ); + /** @var \Drupal\Core\Config\ConfigFactoryInterface $config_factory */ + $config_factory = $this->container->get('config.factory'); $expected = array( - 'content' => array( - 'value' => 'Hello World', - 'format' => 'plain_text', - ), + 'value' => 'Hello World', + 'format' => 'plain_text', ); - $this->assertEqual($expected, $config_parsed_compare); + $actual = $config_factory + ->setOverrideState(FALSE) + ->get('config_translation_test.content') + ->get('content'); + $this->assertEqual($expected, $actual); $translation_base_url = 'admin/config/media/file-system/translate'; $this->drupalGet($translation_base_url); @@ -707,21 +702,24 @@ public function testTextFormatTranslation() { // Update translatable fields. $edit = array( - 'config_names[config_translation_test.content][content][translation][value]' => 'Hello World - FR', + 'config_names[config_translation_test.content][content][value]' => 'Hello World - FR', ); // Save language specific version of form. $this->drupalPostForm($translation_page_url, $edit, t('Save translation')); // Get translation and check we've got the right value. - $config_parsed = $file_storage->read('language.config.fr.config_translation_test.content'); $expected = array( - 'content' => array( - 'value' => 'Hello World - FR', - 'format' => 'plain_text', - ), + 'value' => 'Hello World - FR', + 'format' => 'plain_text', ); - $this->assertEqual($expected, $config_parsed); + $this->container->get('language.config_factory_override') + ->setLanguage(new Language(array('id' => 'fr'))); + $actual = $config_factory + ->setOverrideState(TRUE) + ->get('config_translation_test.content') + ->get('content'); + $this->assertEqual($expected, $actual); } /** diff --git a/core/modules/config_translation/tests/modules/config_translation_test/config/config_translation_test.content.yml b/core/modules/config_translation/tests/modules/config_translation_test/config/install/config_translation_test.content.yml similarity index 100% rename from core/modules/config_translation/tests/modules/config_translation_test/config/config_translation_test.content.yml rename to core/modules/config_translation/tests/modules/config_translation_test/config/install/config_translation_test.content.yml diff --git a/core/modules/config_translation/tests/modules/config_translation_test/config/schema/config_translation_test.schema.yml b/core/modules/config_translation/tests/modules/config_translation_test/config/schema/config_translation_test.schema.yml index cea0fa9..3fcaac3 100644 --- a/core/modules/config_translation/tests/modules/config_translation_test/config/schema/config_translation_test.schema.yml +++ b/core/modules/config_translation/tests/modules/config_translation_test/config/schema/config_translation_test.schema.yml @@ -15,4 +15,4 @@ config_translation_test.content: label: 'Default language' content: type: text_with_format - label: 'Content' \ No newline at end of file + label: 'Content' diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/area/Text.php b/core/modules/views/lib/Drupal/views/Plugin/views/area/Text.php index 86288b0..cbbde55 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/area/Text.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/area/Text.php @@ -38,7 +38,6 @@ public function buildOptionsForm(&$form, &$form_state) { '#default_value' => $this->options['content'], '#rows' => 6, '#format' => isset($this->options['format']) ? $this->options['format'] : filter_default_format(), - '#editor' => FALSE, ); } diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/exposed_form/InputRequired.php b/core/modules/views/lib/Drupal/views/Plugin/views/exposed_form/InputRequired.php index 5508f3a..d207cc7 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/exposed_form/InputRequired.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/exposed_form/InputRequired.php @@ -39,7 +39,6 @@ public function buildOptionsForm(&$form, &$form_state) { '#description' => t('Text to display instead of results until the user selects and applies an exposed filter.'), '#default_value' => $this->options['text_input_required'], '#format' => isset($this->options['text_input_required_format']) ? $this->options['text_input_required_format'] : filter_default_format(), - '#editor' => FALSE, ); }