Commit 2ca1f2db authored by alexpott's avatar alexpott

Issue #2457551 by Gábor Hojtsy, rteijeiro, keopx, eiriksm, alexpott:...

Issue #2457551 by Gábor Hojtsy, rteijeiro, keopx, eiriksm, alexpott: Regression: optional default configuration is not translatable anymore in locale
parent e1396322
......@@ -264,8 +264,6 @@ services:
config.storage.schema:
class: Drupal\Core\Config\ExtensionInstallStorage
arguments: ['@config.storage', 'config/schema']
config.storage.installer:
class: Drupal\Core\Config\InstallStorage
config.typed:
class: Drupal\Core\Config\TypedConfigManager
arguments: ['@config.storage', '@config.storage.schema', '@cache.discovery', '@module_handler']
......
......@@ -233,27 +233,16 @@ public function getLanguageSwitchLinks($type, Url $url) {
}
/**
* Some common languages with their English and native names.
*
* Language codes are defined by the W3C language tags document for
* interoperability. Language codes typically have a language and, optionally,
* a script or regional variant name. See:
* http://www.w3.org/International/articles/language-tags/ for more
* information.
*
* This list is based on languages available from localize.drupal.org. See
* http://localize.drupal.org/issues for information on how to add languages
* there.
*
* The "Left-to-right marker" comments and the enclosed UTF-8 markers are to
* make otherwise strange looking PHP syntax natural (to not be displayed in
* right to left). See http://drupal.org/node/128866#comment-528929.
*
* @return array
* An array of language code to language name information.
* Language name information itself is an array of English and native names.
* @inheritdoc
*/
public static function getStandardLanguageList() {
// This list is based on languages available from localize.drupal.org. See
// http://localize.drupal.org/issues for information on how to add languages
// there.
//
// The "Left-to-right marker" comments and the enclosed UTF-8 markers are to
// make otherwise strange looking PHP syntax natural (to not be displayed in
// right to left). See http://drupal.org/node/128866#comment-528929.
return array(
'af' => array('Afrikaans', 'Afrikaans'),
'am' => array('Amharic', 'አማርኛ'),
......
......@@ -208,4 +208,19 @@ public function setConfigOverrideLanguage(LanguageInterface $language = NULL);
*/
public function getConfigOverrideLanguage();
/**
* Some common languages with their English and native names.
*
* Language codes are defined by the W3C language tags document for
* interoperability. Language codes typically have a language and, optionally,
* a script or regional variant name. See:
* http://www.w3.org/International/articles/language-tags/ for more
* information.
*
* @return array
* An array of language code to language name information. Language name
* information itself is an array of English and native names.
*/
public static function getStandardLanguageList();
}
......@@ -7,6 +7,7 @@
namespace Drupal\config\Tests;
use Drupal\Core\Config\InstallStorage;
use Drupal\Core\Config\PreExistingConfigException;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Config\UnmetDependenciesException;
......@@ -223,7 +224,8 @@ public function testDependencyChecking() {
function testLanguage() {
$this->installModules(['config_test_language']);
// Test imported configuration with implicit language code.
$data = $this->container->get('config.storage.installer')->read('config_test.dynamic.dotted.english');
$storage = new InstallStorage();
$data = $storage->read('config_test.dynamic.dotted.english');
$this->assertTrue(!isset($data['langcode']));
$this->assertEqual(
$this->config('config_test.dynamic.dotted.english')->get('langcode'),
......@@ -231,7 +233,7 @@ function testLanguage() {
);
// Test imported configuration with explicit language code.
$data = $this->container->get('config.storage.installer')->read('config_test.dynamic.dotted.french');
$data = $storage->read('config_test.dynamic.dotted.french');
$this->assertEqual($data['langcode'], 'fr');
$this->assertEqual(
$this->config('config_test.dynamic.dotted.french')->get('langcode'),
......
......@@ -407,23 +407,30 @@ function locale_system_update(array $components) {
// Skip running the translation imports if in the installer,
// because it would break out of the installer flow. We have
// built-in support for translation imports in the installer.
if (!drupal_installation_attempted() && locale_translatable_language_list() && \Drupal::config('locale.settings')->get('translation.import_enabled')) {
module_load_include('compare.inc', 'locale');
// Update the list of translatable projects and start the import batch.
// Only when new projects are added the update batch will be triggered. Not
// each enabled module will introduce a new project. E.g. sub modules.
$projects = array_keys(locale_translation_build_projects());
if ($list = array_intersect($list, $projects)) {
module_load_include('fetch.inc', 'locale');
// Get translation status of the projects, download and update
// translations.
$options = _locale_translation_default_update_options();
$batch = locale_translation_batch_update_build($list, array(), $options);
batch_set($batch);
if (!drupal_installation_attempted() && locale_translatable_language_list()) {
if (\Drupal::config('locale.settings')->get('translation.import_enabled')) {
module_load_include('compare.inc', 'locale');
// Update the list of translatable projects and start the import batch.
// Only when new projects are added the update batch will be triggered.
// Not each enabled module will introduce a new project. E.g. sub modules.
$projects = array_keys(locale_translation_build_projects());
if ($list = array_intersect($list, $projects)) {
module_load_include('fetch.inc', 'locale');
// Get translation status of the projects, download and update
// translations.
$options = _locale_translation_default_update_options();
$batch = locale_translation_batch_update_build($list, [], $options);
batch_set($batch);
}
}
// Construct a batch to update configuration for all components. Installing
// this component may have installed configuration from any number of other
// components. Do this even if import is not enabled because parsing new
// configuration may expose new source strings.
\Drupal::moduleHandler()->loadInclude('locale', 'bulk.inc');
if ($batch = locale_config_batch_update_components(array(), array(), $components)) {
if ($batch = locale_config_batch_update_components([])) {
batch_set($batch);
}
}
......
services:
locale.default.config.storage:
class: Drupal\locale\LocaleDefaultConfigStorage
arguments: ['@config.storage', '@language_manager']
public: false
locale.config_manager:
class: Drupal\locale\LocaleConfigManager
arguments: ['@config.storage', '@config.storage.installer', '@locale.storage', '@config.factory', '@config.typed', '@language_manager']
arguments: ['@config.storage', '@locale.storage', '@config.factory', '@config.typed', '@language_manager', '@locale.default.config.storage']
locale.storage:
class: Drupal\locale\StringDatabaseStorage
arguments: ['@database']
......
......@@ -9,6 +9,7 @@
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\InstallStorage;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Config\TypedConfigManagerInterface;
use Drupal\Core\StringTranslation\TranslationWrapper;
......@@ -44,13 +45,6 @@ class LocaleConfigManager {
*/
protected $configStorage;
/**
* The storage instance for reading default configuration data.
*
* @var \Drupal\Core\Config\StorageInterface
*/
protected $installStorage;
/**
* The string storage for reading and writing translations.
*
......@@ -95,14 +89,18 @@ class LocaleConfigManager {
*/
protected $isUpdatingFromLocale = FALSE;
/**
* The locale default config storage instance.
*
* @var \Drupal\locale\LocaleDefaultConfigStorage
*/
protected $defaultConfigStorage;
/**
* Creates a new typed configuration manager.
*
* @param \Drupal\Core\Config\StorageInterface $config_storage
* The storage object to use for reading configuration data.
* @param \Drupal\Core\Config\StorageInterface $install_storage
* The storage object to use for reading default configuration
* data.
* @param \Drupal\locale\StringStorageInterface $locale_storage
* The locale storage to use for reading string translations.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
......@@ -111,14 +109,16 @@ class LocaleConfigManager {
* The typed configuration manager.
* @param \Drupal\language\ConfigurableLanguageManagerInterface $language_manager
* The language manager.
* @param \Drupal\locale\LocaleDefaultConfigStorage $default_config_storage
* The locale default configuration storage.
*/
public function __construct(StorageInterface $config_storage, StorageInterface $install_storage, StringStorageInterface $locale_storage, ConfigFactoryInterface $config_factory, TypedConfigManagerInterface $typed_config, ConfigurableLanguageManagerInterface $language_manager) {
public function __construct(StorageInterface $config_storage, StringStorageInterface $locale_storage, ConfigFactoryInterface $config_factory, TypedConfigManagerInterface $typed_config, ConfigurableLanguageManagerInterface $language_manager, LocaleDefaultConfigStorage $default_config_storage) {
$this->configStorage = $config_storage;
$this->installStorage = $install_storage;
$this->localeStorage = $locale_storage;
$this->configFactory = $config_factory;
$this->typedConfigManager = $typed_config;
$this->languageManager = $language_manager;
$this->defaultConfigStorage = $default_config_storage;
}
/**
......@@ -133,7 +133,7 @@ public function __construct(StorageInterface $config_storage, StorageInterface $
public function getTranslatableDefaultConfig($name) {
if ($this->isSupported($name)) {
// Create typed configuration wrapper based on install storage data.
$data = $this->installStorageRead($name);
$data = $this->defaultConfigStorage->read($name);
$type_definition = $this->typedConfigManager->getDefinition($name);
$data_definition = $this->typedConfigManager->buildDataDefinition($type_definition, $data);
$typed_config = $this->typedConfigManager->create($data_definition, $data);
......@@ -293,12 +293,12 @@ public function getComponentNames(array $components = array()) {
foreach ($components as $type => $list) {
// InstallStorage::getComponentNames returns a list of folders keyed by
// config name.
$names = array_merge($names, $this->installStorageComponents($type, $list));
$names = array_merge($names, $this->defaultConfigStorage->getComponentNames($type, $list));
}
return $names;
}
else {
return $this->installStorageAll();
return $this->defaultConfigStorage->listAll();
}
}
......@@ -474,7 +474,7 @@ public function hasTranslation($name, $langcode) {
* configuration exists.
*/
public function getDefaultConfigLangcode($name) {
$shipped = $this->installStorageRead($name);
$shipped = $this->defaultConfigStorage->read($name);
if (!empty($shipped)) {
return !empty($shipped['langcode']) ? $shipped['langcode'] : 'en';
}
......@@ -635,81 +635,4 @@ protected function filterOverride(array $override_data, array $translatable) {
return $filtered_data;
}
/**
* Read a configuration from install storage or default languages.
*
* @param string $name
* Configuration object name.
*
* @return array
* Configuration data from install storage or default language.
*/
protected function installStorageRead($name) {
if ($this->installStorage->exists($name)) {
return $this->installStorage->read($name);
}
elseif (strpos($name, 'language.entity.') === 0) {
// Simulate default languages as if they were shipped as default
// configuration.
$langcode = str_replace('language.entity.', '', $name);
$predefined_languages = $this->languageManager->getStandardLanguageList();
if (isset($predefined_languages[$langcode])) {
$data = $this->configStorage->read($name);
$data['label'] = $predefined_languages[$langcode][0];
return $data;
}
}
}
/**
* Return the list of configuration in install storage and current languages.
*
* @return array
* List of configuration in install storage and current languages.
*/
protected function installStorageAll() {
$languages = $this->predefinedConfiguredLanguages();
return array_unique(array_merge($this->installStorage->listAll(), $languages));
}
/**
* Get all configuration names and folders for a list of modules or themes.
*
* @param string $type
* Type of components: 'module' | 'theme' | 'profile'
* @param array $list
* Array of theme or module names.
*
* @return array
* Configuration names provided by that component. In case of language
* module this list is extended with configured languages that have
* predefined names as well.
*/
protected function installStorageComponents($type, array $list) {
$names = array_keys($this->installStorage->getComponentNames($type, $list));
if ($type == 'module' && in_array('language', $list)) {
$languages = $this->predefinedConfiguredLanguages();
$names = array_unique(array_merge($names, $languages));
}
return $names;
}
/**
* Compute the list of configuration names that match predefined languages.
*
* @return array
* The list of configuration names that match predefined languages.
*/
protected function predefinedConfiguredLanguages() {
$names = $this->configStorage->listAll('language.entity.');
$predefined_languages = $this->languageManager->getStandardLanguageList();
foreach ($names as $id => $name) {
$langcode = str_replace('language.entity.', '', $name);
if (!isset($predefined_languages[$langcode])) {
unset($names[$id]);
}
}
return array_values($names);
}
}
<?php
/**
* @file
* Contains \Drupal\locale\LocaleDefaultConfigStorage.
*/
namespace Drupal\locale;
use Drupal\Core\Config\InstallStorage;
use Drupal\Core\Config\StorageInterface;
use Drupal\language\ConfigurableLanguageManagerInterface;
/**
* Provides access to default configuration for locale integration.
*
* Allows unified access to default configuration from one of three sources:
* - Required default configuration (config/install/*)
* - Optional default configuration (config/optional/*)
* - Predefined languages mocked as default configuration (list defined in
* LocaleConfigManagerInterface::getStandardLanguageList())
*
* These sources are considered equal in terms of how locale module interacts
* with them for translation. Their translatable source strings are exposed
* for interface translation and participate in remote translation updates.
*/
class LocaleDefaultConfigStorage {
/**
* The storage instance for reading configuration data.
*
* @var \Drupal\Core\Config\StorageInterface
*/
protected $configStorage;
/**
* The language manager.
*
* @var \Drupal\language\ConfigurableLanguageManagerInterface
*/
protected $languageManager;
/**
* The storage instance for reading required default configuration data.
*
* @var \Drupal\Core\Config\StorageInterface
*/
protected $requiredInstallStorage;
/**
* The storage instance for reading optional default configuration data.
*
* @var \Drupal\Core\Config\StorageInterface
*/
protected $optionalInstallStorage;
/**
* Constructs a LocaleDefaultConfigStorage.
*
* @param \Drupal\Core\Config\StorageInterface $config_storage
* The storage object to use for reading configuration data.
* @param \Drupal\language\ConfigurableLanguageManagerInterface $language_manager
* The language manager.
*/
public function __construct(StorageInterface $config_storage, ConfigurableLanguageManagerInterface $language_manager) {
$this->configStorage = $config_storage;
$this->languageManager = $language_manager;
$this->requiredInstallStorage = new InstallStorage();
$this->optionalInstallStorage = new InstallStorage(InstallStorage::CONFIG_OPTIONAL_DIRECTORY);
}
/**
* Read a configuration from install storage or default languages.
*
* @param string $name
* Configuration object name.
*
* @return array
* Configuration data from install storage or default language.
*/
public function read($name) {
if ($this->requiredInstallStorage->exists($name)) {
return $this->requiredInstallStorage->read($name);
}
elseif ($this->optionalInstallStorage->exists($name)) {
return $this->optionalInstallStorage->read($name);
}
elseif (strpos($name, 'language.entity.') === 0) {
// Simulate default languages as if they were shipped as default
// configuration.
$langcode = str_replace('language.entity.', '', $name);
$predefined_languages = $this->languageManager->getStandardLanguageList();
if (isset($predefined_languages[$langcode])) {
$data = $this->configStorage->read($name);
$data['label'] = $predefined_languages[$langcode][0];
return $data;
}
}
}
/**
* Return the list of configuration in install storage and current languages.
*
* @return array
* List of configuration in install storage and current languages.
*/
public function listAll() {
$languages = $this->predefinedConfiguredLanguages();
return array_unique(
array_merge(
$this->requiredInstallStorage->listAll(),
$this->optionalInstallStorage->listAll(),
$languages
)
);
}
/**
* Get all configuration names and folders for a list of modules or themes.
*
* @param string $type
* Type of components: 'module' | 'theme' | 'profile'
* @param array $list
* Array of theme or module names.
*
* @return array
* Configuration names provided by that component. In case of language
* module this list is extended with configured languages that have
* predefined names as well.
*/
public function getComponentNames($type, array $list) {
$names = array_unique(
array_merge(
array_keys($this->requiredInstallStorage->getComponentNames($type, $list)),
array_keys($this->optionalInstallStorage->getComponentNames($type, $list))
)
);
if ($type == 'module' && in_array('language', $list)) {
$languages = $this->predefinedConfiguredLanguages();
$names = array_unique(array_merge($names, $languages));
}
return $names;
}
/**
* Compute the list of configuration names that match predefined languages.
*
* @return array
* The list of configuration names that match predefined languages.
*/
protected function predefinedConfiguredLanguages() {
$names = $this->configStorage->listAll('language.entity.');
$predefined_languages = $this->languageManager->getStandardLanguageList();
foreach ($names as $id => $name) {
$langcode = str_replace('language.entity.', '', $name);
if (!isset($predefined_languages[$langcode])) {
unset($names[$id]);
}
}
return array_values($names);
}
}
......@@ -8,6 +8,7 @@
namespace Drupal\locale\Tests;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\locale\Locale;
use Drupal\locale\StringInterface;
use Drupal\locale\TranslationString;
use Drupal\simpletest\KernelTestBase;
......@@ -22,7 +23,7 @@ class LocaleConfigSubscriberTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['language', 'locale'];
public static $modules = ['language', 'locale', 'system'];
/**
* The configurable language manager used in this test.
......@@ -61,6 +62,7 @@ protected function setUp() {
$this->setUpDefaultLanguage();
$this->installSchema('locale', ['locales_source', 'locales_target', 'locales_location']);
$this->installSchema('system', ['queue']);
$this->setupLanguages();
......@@ -68,7 +70,12 @@ protected function setUp() {
$this->installConfig(['locale_test']);
// Simulate this hook invoked which would happen if in a non-kernel test
// or normal environment.
locale_modules_installed(array('locale_test'));
// @see locale_modules_installed()
// @see locale_system_update()
locale_system_set_config_langcodes();
$langcodes = array_keys(\Drupal::languageManager()->getLanguages());
$names = \Drupal\locale\Locale::config()->getComponentNames();
Locale::config()->updateConfigTranslations($names, $langcodes);
$this->configFactory = $this->container->get('config.factory');
$this->stringStorage = $this->container->get('locale.storage');
......
......@@ -18,6 +18,13 @@
*/
class LocaleConfigTranslationTest extends WebTestBase {
/**
* The language code used.
*
* @var string
*/
protected $langcode;
/**
* Modules to enable.
*
......@@ -38,28 +45,28 @@ protected function setUp() {
$this->config('locale.settings')
->set('translation.import_enabled', TRUE)
->save();
}
/**
* Tests basic configuration translation.
*/
public function testConfigTranslation() {
// Add custom language.
$langcode = 'xx';
$this->langcode = 'xx';
$admin_user = $this->drupalCreateUser(array('administer languages', 'access administration pages', 'translate interface', 'administer modules', 'access site-wide contact form', 'administer contact forms', 'administer site configuration'));
$this->drupalLogin($admin_user);
$name = $this->randomMachineName(16);
$edit = array(
'predefined_langcode' => 'custom',
'langcode' => $langcode,
'langcode' => $this->langcode,
'label' => $name,
'direction' => LanguageInterface::DIRECTION_LTR,
);
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language'));
// Set path prefix.
$edit = array("prefix[$langcode]" => $langcode);
$edit = ["prefix[$this->langcode]" => $this->langcode];
$this->drupalPostForm('admin/config/regional/language/detection/url', $edit, t('Save configuration'));
}
/**
* Tests basic configuration translation.
*/
public function testConfigTranslation() {
// Check that the maintenance message exists and create translation for it.
$source = '@site is currently under maintenance. We should be back shortly. Thank you for your patience.';
$string = $this->storage->findString(array('source' => $source, 'context' => '', 'type' => 'configuration'));
......@@ -69,7 +76,7 @@ public function testConfigTranslation() {
$message = $this->randomMachineName(20);
$search = array(
'string' => $string->source,
'langcode' => $langcode,
'langcode' => $this->langcode,
'translation' => 'all',
);
$this->drupalPostForm('admin/config/regional/translate', $search, t('Filter'));
......@@ -82,7 +89,7 @@ public function testConfigTranslation() {
$this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations'));
// Get translation and check we've only got the message.
$translation = \Drupal::languageManager()->getLanguageConfigOverride($langcode, 'system.maintenance')->get();
$translation = \Drupal::languageManager()->getLanguageConfigOverride($this->langcode, 'system.maintenance')->get();
$this->assertEqual(count($translation), 1, 'Got the right number of properties after translation.');
$this->assertEqual($translation['message'], $message);
......@@ -93,7 +100,7 @@ public function testConfigTranslation() {
// Translate using the UI so configuration is refreshed.
$search = array(
'string' => $string->source,
'langcode' => $langcode,
'langcode' => $this->langcode,
'translation' => 'all',
);
$this->drupalPostForm('admin/config/regional/translate', $search, t('Filter'));
......@@ -105,12 +112,12 @@ public function testConfigTranslation() {
);
$this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations'));
$translation = \Drupal::languageManager()->getLanguageConfigOverride($langcode, 'core.date_format.medium')->get();
$translation = \Drupal::languageManager()->getLanguageConfigOverride($this->langcode, 'core.date_format.medium')->get();
$this->assertEqual($translation['pattern'], 'D', 'Got the right date format pattern after translation.');
// Formatting the date 8 / 27 / 1985 @ 13:37 EST with pattern D should
// display "Tue".
$formatted_date = format_date(494015820, $type = 'medium', NULL, NULL, $langcode);
$formatted_date = format_date(494015820, $type = 'medium', NULL, NULL, $this->langcode);
$this->assertEqual($formatted_date, 'Tue', 'Got the right formatted date using the date format translation pattern.');
// Assert strings from image module config are not available.
......@@ -127,7 +134,7 @@ public function testConfigTranslation() {
$this->assertTrue(isset($locations['configuration']) && isset($locations['configuration']['image.style.medium']), 'Configuration string has been created with the right location');
// Check the string is unique and has no translation yet.
$translations = $this->storage->getTranslations(array('language' => $langcode, 'type' => 'configuration', 'name' => 'image.style.medium'));
$translations = $this->storage->getTranslations(['language' => $this->langcode, 'type' => 'configuration', 'name' => 'image.style.medium']);
$this->assertEqual(count($translations), 1);
$translation = reset($translations);
$this->assertEqual($translation->source, $string->source);
......@@ -137,7 +144,7 @@ public function testConfigTranslation() {
$image_style_label = $this->randomMachineName(20);
$search = array(
'string' => $string->source,
'langcode' => $langcode,
'langcode' => $this->langcode,
'translation' => 'all',
);
$this->drupalPostForm('admin/config/regional/translate', $search, t('Filter'));
......@@ -149,12 +156,12 @@ public function testConfigTranslation() {
$this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations'));
// Check the right single translation has been created.
$translations = $this->storage->getTranslations(array('language' => $langcode, 'type' => 'configuration', 'name' => 'image.style.medium'));
$translations = $this->storage->getTranslations(['language' => $this->langcode, 'type' => 'configuration', 'name' => 'image.style.medium']);
$translation = reset($translations);
$this->assertTrue(count($translations) == 1 && $translation->source == $string->source && $translation->translation == $image_style_label, 'Got only one translation for image configuration.');
// Try more complex configuration data.
$translation = \Drupal::languageManager()->getLanguageConfigOverride($langcode, 'image.style.medium')->get();
$translation = \Drupal::languageManager()->getLanguageConfigOverride($this->langcode, 'image.style.medium')->get();
$this->assertEqual($translation['label'], $image_style_label, 'Got the right translation for image style name after translation');
// Uninstall the module.
......@@ -169,7 +176,7 @@ public function testConfigTranslation() {
$category_label = $this->randomMachineName(20);
$search = array(
'string' => 'Website feedback',
'langcode' => $langcode,
'langcode' => $this->langcode,
'translation' => 'all',
);
$this->drupalPostForm('admin/config/regional/translate', $search, t('Filter'));
......@@ -183,7 +190,7 @@ public function testConfigTranslation() {
// Check if this category displayed in this language will use the
// translation. This test ensures the entity loaded from the request
// upcasting will already work.
$this->drupalGet($langcode . '/contact/feedback');
$this->drupalGet($this->langcode . '/contact/feedback');
$this->assertText($category_label);
// Check if the UI does not show the translated String.
......@@ -191,4 +198,54 @@ public function testConfigTranslation() {
$this->assertFieldById('edit-label', 'Website feedback', 'Translation is not loaded for Edit Form.');
}
/**
* Test translatability of optional configuration in locale.
*/
public function testOptionalConfiguration() {
$this->assertNodeConfig(FALSE, FALSE);
// Enable the node module.
$this->drupalPostForm('admin/modules', ['modules[Core][node][enable]' => "1"], t('Save configuration'));
$this->drupalPostForm(NULL, [], t('Continue'));
$this->rebuildContainer();
$this->assertNodeConfig(TRUE, FALSE);
// Enable the views module (which node provides some optional config for).
$this->drupalPostForm('admin/modules', ['modules[Core][views][enable]' => "1"], t('Save configuration'));
$this->rebuildContainer();
$this->assertNodeConfig(TRUE, TRUE);
}
/**
* Check that node configuration source strings are made available in locale.
*
* @param bool $required
* Whether to assume a sample of the required default configuration is
* present.
* @param bool $optional
* Whether to assume a sample of the optional default configuration is
* present.
*/
protected function assertNodeConfig($required, $optional) {
// Check the required default configuration in node module.
$string = $this->storage->findString(['source' => 'Make content sticky', 'context' => '', 'type' => 'configuration']);
if ($required) {
$this->assertFalse($this->config('system.action.node_make_sticky_action')->isNew());
$this->assertTrue($string, 'Node action text can be found with node module.');