Commit c34478f5 authored by alexpott's avatar alexpott

Issue #2212069 by Gábor Hojtsy, pjonckiere, rteijeiro, cilefen: Non-English...

Issue #2212069 by Gábor Hojtsy, pjonckiere, rteijeiro, cilefen: Non-English Drupal sites get default configuration in English, edited in English, originals not actually used if translated
parent ae3dc626
......@@ -67,12 +67,12 @@ static function getSubscribedEvents() {
*/
protected function filterOverride(Config $config, StorableConfigBase $override) {
$override_data = $override->get();
$this->filterNestedArray($config->get(), $override_data);
$changed = $this->filterNestedArray($config->get(), $override_data);
if (empty($override_data)) {
// If no override values are left that would apply, remove the override.
$override->delete();
}
else {
elseif ($changed) {
// Otherwise set the filtered override values back.
$override->setData($override_data)->save();
}
......@@ -85,29 +85,37 @@ protected function filterOverride(Config $config, StorableConfigBase $override)
* Original data array to filter against.
* @param array $override_data
* Override data to filter.
*
* @return bool
* TRUE if $override_data was changed, FALSE otherwise.
*/
protected function filterNestedArray(array $original_data, array &$override_data) {
$changed = FALSE;
foreach ($override_data as $key => $value) {
if (!isset($original_data[$key])) {
// The original data is not there anymore, remove the override.
unset($override_data[$key]);
$changed = TRUE;
}
elseif (is_array($override_data[$key])) {
if (is_array($original_data[$key])) {
// Do the filtering one level deeper.
$this->filterNestedArray($original_data[$key], $override_data[$key]);
$changed = $this->filterNestedArray($original_data[$key], $override_data[$key]);
// If no overrides are left under this level, remove the level.
if (empty($override_data[$key])) {
unset($override_data[$key]);
$changed = TRUE;
}
}
else {
// The override is an array but the value is not, this will not go
// well, remove the override.
unset($override_data[$key]);
$changed = TRUE;
}
}
}
return $changed;
}
}
......@@ -53,7 +53,7 @@ public function checkConfigSchema(TypedConfigManagerInterface $typed_config, $co
if (!$typed_config->hasConfigSchema($config_name)) {
return FALSE;
}
$definition = $typed_config->getDefinition($config_name);
$definition = $typed_config->getDefinition($config_name, TRUE, TRUE);
$data_definition = $typed_config->buildDataDefinition($definition, $config_data);
$this->schema = $typed_config->create($data_definition, $config_data);
$errors = array();
......
......@@ -128,7 +128,7 @@ public function getStorage() {
*/
protected function getSchemaWrapper() {
if (!isset($this->schemaWrapper)) {
$definition = $this->typedConfigManager->getDefinition($this->name);
$definition = $this->typedConfigManager->getDefinition($this->name, TRUE, TRUE);
$data_definition = $this->typedConfigManager->buildDataDefinition($definition, $this->data);
$this->schemaWrapper = $this->typedConfigManager->create($data_definition, $this->data);
}
......
......@@ -72,8 +72,8 @@ public function __construct(StorageInterface $configStorage, StorageInterface $s
*/
public function get($name) {
$data = $this->configStorage->read($name);
$type_definition = $this->getDefinition($name);
$data_definition = $this->buildDataDefinition($type_definition, $data);
$type_definition = $this->getDefinition($name, TRUE, TRUE);
$data_definition = $this->buildDataDefinition($type_definition, $data);
return $this->create($data_definition, $data);
}
......@@ -116,7 +116,7 @@ public function buildDataDefinition(array $definition, $value, $name = NULL, $pa
/**
* {@inheritdoc}
*/
public function getDefinition($base_plugin_id, $exception_on_invalid = TRUE) {
public function getDefinition($base_plugin_id, $exception_on_invalid = TRUE, $is_config_name = FALSE) {
$definitions = $this->getDefinitions();
if (isset($definitions[$base_plugin_id])) {
$type = $base_plugin_id;
......@@ -141,10 +141,19 @@ public function getDefinition($base_plugin_id, $exception_on_invalid = TRUE) {
$this->definitions[$type] = $definition;
}
// Add type and default definition class.
return $definition + array(
$definition += array(
'definition_class' => '\Drupal\Core\TypedData\DataDefinition',
'type' => $type,
);
// If this is definition expected for a config name and it is defined as a
// mapping, add a langcode element if not already present.
if ($is_config_name && isset($definition['mapping']) && !isset($definition['mapping']['langcode'])) {
$definition['mapping']['langcode'] = array(
'type' => 'string',
'label' => 'Language code',
);
}
return $definition;
}
/**
......
......@@ -102,4 +102,24 @@ public function buildDataDefinition(array $definition, $value, $name = NULL, $pa
*/
public function hasConfigSchema($name);
/**
* Gets a specific plugin definition.
*
* @param string $plugin_id
* A plugin id.
* @param bool $exception_on_invalid
* Ignored with TypedConfigManagerInterface. Kept for compatibility with
* DiscoveryInterface.
* @param bool $is_config_name
* Set to TRUE if $plugin_id is a configuration name (as opposed to an
* internal configuration schema type).
*
* @return array
* A plugin definition array. If the given plugin id does not have typed
* configuration definition assigned, the definition of an undefined
* element type is returned. If $is_config_name is set, a langcode key
* is automatically added to the definition.
*/
public function getDefinition($plugin_id, $exception_on_invalid = TRUE, $is_config_name = FALSE);
}
......@@ -59,6 +59,29 @@ public function __construct($string, array $arguments = array(), array $options
$this->options = $options;
}
/**
* Gets the untranslated string value stored in this translation wrapper.
*
* @return string
* The string stored in this wrapper.
*/
public function getUntranslatedString() {
return $this->string;
}
/**
* Gets a specific option from this translation wrapper.
*
* @param $name
* Option name.
*
* @return mixed
* The value of this option or empty string of option is not set.
*/
public function getOption($name) {
return isset($this->options[$name]) ? $this->options[$name] : '';
}
/**
* Implements the magic __toString() method.
*/
......
......@@ -26,7 +26,7 @@ class ConfigSchemaTest extends KernelTestBase {
*
* @var array
*/
public static $modules = array('system', 'language', 'locale', 'field', 'image', 'config_test', 'config_schema_test');
public static $modules = array('system', 'language', 'field', 'image', 'config_test', 'config_schema_test');
/**
* {@inheritdoc}
......
......@@ -98,7 +98,7 @@ public static function create(ContainerInterface $container, array $configuratio
$plugin_definition,
$container->get('config.factory'),
$container->get('config.typed'),
$container->get('locale.config.typed'),
$container->get('locale.config_manager'),
$container->get('plugin.manager.config_translation.mapper'),
$container->get('router.route_provider'),
$container->get('string_translation'),
......
......@@ -204,22 +204,6 @@ public function getConfigData();
*/
public function getLangcode();
/**
* Returns language object for the configuration.
*
* If the language of the configuration files is not a configured language on
* the site and it is English, we return a dummy language object to represent
* the built-in language.
*
* @return \Drupal\Core\Language\LanguageInterface
* A configured language object instance or a dummy English language object.
*
* @throws \RuntimeException
* Throws an exception if the language codes in the config files don't
* match.
*/
public function getLanguageWithFallback();
/**
* Returns the name of the type of data the mapper encapsulates.
*
......
......@@ -150,7 +150,7 @@ public static function create(ContainerInterface $container, array $configuratio
$plugin_definition,
$container->get('config.factory'),
$container->get('config.typed'),
$container->get('locale.config.typed'),
$container->get('locale.config_manager'),
$container->get('plugin.manager.config_translation.mapper'),
$container->get('router.route_provider'),
$container->get('string_translation'),
......@@ -407,24 +407,6 @@ public function getLangcode() {
return reset($langcodes);
}
/**
* {@inheritdoc}
*/
public function getLanguageWithFallback() {
$langcode = $this->getLangcode();
$language = $this->languageManager->getLanguage($langcode);
// If the language of the file is English but English is not a configured
// language on the site, create a mock language object to represent this
// language run-time. In this case, the title of the language is
// 'Built-in English' because we assume such configuration is shipped with
// core and the modules and not custom created. (In the later case an
// English language configured on the site is assumed.)
if (empty($language) && $langcode == 'en') {
$language = new Language(array('id' => 'en', 'name' => $this->t('Built-in English')));
}
return $language;
}
/**
* {@inheritdoc}
*/
......@@ -465,7 +447,7 @@ public function hasTranslatable() {
*/
public function hasTranslation(LanguageInterface $language) {
foreach ($this->getConfigNames() as $name) {
if ($this->localeConfigManager->hasTranslation($name, $language)) {
if ($this->localeConfigManager->hasTranslation($name, $language->getId())) {
return TRUE;
}
}
......
......@@ -127,18 +127,12 @@ public function itemPage(Request $request, RouteMatchInterface $route_match, $pl
$page = array();
$page['#title'] = $this->t('Translations for %label', array('%label' => $mapper->getTitle()));
// It is possible the original language this configuration was saved with is
// not on the system. For example, the configuration shipped in English but
// the site has no English configured. Represent the original language in
// the table even if it is not currently configured.
$languages = $this->languageManager->getLanguages();
$original_langcode = $mapper->getLangcode();
if (!isset($languages[$original_langcode])) {
// If the language is not configured on the site, create a dummy language
// object for this listing only to ensure the user gets useful info.
$language_name = $this->languageManager->getLanguageName($original_langcode);
if ($original_langcode == 'en') {
$language_name = $this->t('Built-in English');
}
// Create a dummy language object for this listing only.
$languages[$original_langcode] = new Language(array('id' => $original_langcode, 'name' => $language_name));
}
......
......@@ -144,7 +144,7 @@ public function buildForm(array $form, FormStateInterface $form_state, Request $
$this->mapper = $mapper;
$this->language = $language;
$this->sourceLanguage = $this->mapper->getLanguageWithFallback();
$this->sourceLanguage = $this->languageManager->getLanguage($this->mapper->getLangcode());
// Get base language configuration to display in the form before setting the
// language to use for the form. This avoids repetitively settings and
......
......@@ -589,7 +589,7 @@ public function testHasTranslation(array $mock_return_values, $expected) {
$map = array();
foreach ($config_names as $i => $config_name) {
$map[] = array($config_name, $language, $mock_return_values[$i]);
$map[] = array($config_name, $language->getId(), $mock_return_values[$i]);
}
$this->localeConfigManager
->expects($this->any())
......
......@@ -161,21 +161,6 @@ function language_process_language_select($element) {
$element['#options'][$langcode] = $language->isLocked() ? t('- @name -', array('@name' => $language->getName())) : $language->getName();
}
}
// Add "Built-in English" language to the select when the default value is
// set to English but it does not exist in the options list.
//
// Drupal core includes configuration shipped in English, including default
// views, content types, user roles, filter formats, etc. To keep the Drupal
// software update-able, as well as translations update-able, we keep these
// configuration files in English even when installed in a foreign language.
// However, administrators can remove English, in which case editing such a
// configuration would lead to the language settings being changed on it. We
// avoid that by including this option and letting administrators keep it
// in English.
if (isset($element['#default_value']) && $element['#default_value'] == 'en' && !isset($element['#options']['en'])) {
// Prepend the default language at the beginning of the list.
$element['#options'] = array('en' => t('Built-in English')) + $element['#options'];
}
return $element;
}
......
......@@ -117,10 +117,6 @@ public function preSave(EntityStorageInterface $storage) {
// rebuild services if necessary during
// \Drupal\language\Entity\ConfigurableLanguage::postSave().
$this->preSaveMultilingual = \Drupal::languageManager()->isMultilingual();
// Languages are picked from a predefined list which is given in English.
// For the uncommon case of custom languages the label should be given in
// English.
$this->langcode = 'en';
}
/**
......
......@@ -75,7 +75,7 @@ public function commonForm(array &$form) {
}
$form['label'] = array(
'#type' => 'textfield',
'#title' => $this->t('Language name in English'),
'#title' => $this->t('Language name'),
'#maxlength' => 64,
'#default_value' => $language->label(),
'#required' => TRUE,
......
......@@ -132,7 +132,7 @@ function testLanguageConfiguration() {
);
$this->drupalPostForm('admin/config/regional/language/add', $edit, 'Add language');
$language = $this->config('language.entity.de')->get();
$this->assertEqual($language['langcode'], 'en');
$this->assertEqual($language['langcode'], 'fr');
// Ensure that German language has a weight of 5 after being created through
// the UI.
......
......@@ -41,7 +41,7 @@ public function testLanguageConfiguration() {
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language'));
// Test validation on missing values.
$this->assertText(t('!name field is required.', array('!name' => t('Language code'))));
$this->assertText(t('!name field is required.', array('!name' => t('Language name in English'))));
$this->assertText(t('!name field is required.', array('!name' => t('Language name'))));
$empty_language = new Language();
$this->assertFieldChecked('edit-direction-' . $empty_language->getDirection(), 'Consistent usage of language direction.');
$this->assertUrl(\Drupal::url('language.add', array(), array('absolute' => TRUE)), [], 'Correct page redirection.');
......@@ -60,7 +60,7 @@ public function testLanguageConfiguration() {
'@url' => 'http://www.w3.org/International/articles/language-tags/',
)));
$this->assertRaw(t('%field cannot contain any markup.', array('%field' => t('Language name in English'))));
$this->assertRaw(t('%field cannot contain any markup.', array('%field' => t('Language name'))));
$this->assertUrl(\Drupal::url('language.add', array(), array('absolute' => TRUE)), [], 'Correct page redirection.');
// Test adding a custom language with a numeric region code.
......
......@@ -324,7 +324,7 @@ function locale_translate_batch_refresh(array &$context) {
}
elseif ($name = array_shift($context['sandbox']['refresh']['names'])) {
// Refresh all languages for one object at a time.
$count = locale_config_update_multiple(array($name), $context['sandbox']['refresh']['languages']);
$count = Locale::config()->updateConfigTranslations(array($name), $context['sandbox']['refresh']['languages']);
$context['results']['stats']['config'] += $count;
// Inherit finished information from the "parent" string lookup step so
// visual display of status will make sense.
......@@ -532,7 +532,7 @@ function locale_translate_delete_translation_files(array $projects = array(), ar
* The batch definition.
*/
function locale_config_batch_update_components(array $options, array $langcodes = array(), array $components = array()) {
$langcodes = $langcodes ? $langcodes : array_keys(locale_translatable_language_list());
$langcodes = $langcodes ? $langcodes : array_keys(\Drupal::languageManager()->getLanguages());
if ($langcodes && $names = \Drupal\locale\Locale::config()->getComponentNames($components)) {
return locale_config_batch_build($names, $langcodes, $options);
}
......@@ -606,7 +606,7 @@ function locale_config_batch_refresh_name(array $names, array $langcodes, array
if (!isset($context['result']['stats']['config'])) {
$context['result']['stats']['config'] = 0;
}
$context['result']['stats']['config'] += locale_config_update_multiple($names, $langcodes);
$context['result']['stats']['config'] += Locale::config()->updateConfigTranslations($names, $langcodes);
foreach ($names as $name) {
$context['result']['names'][] = $name;
}
......@@ -639,41 +639,3 @@ function locale_config_batch_finished($success, array $results) {
}
}
}
/**
* Updates all configuration for names / languages.
*
* @param array $names
* Array of names of configuration objects to update.
* @param array $langcodes
* (optional) Array of language codes to update. Defaults to all languages.
*
* @return int
* Number of configuration objects retranslated.
*/
function locale_config_update_multiple(array $names, array $langcodes = array()) {
/** @var \Drupal\language\ConfigurableLanguageManagerInterface $language_manager */
$language_manager = \Drupal::languageManager();
$locale_config_manager = Locale::config();
$langcodes = $langcodes ? $langcodes : array_keys(locale_translatable_language_list());
$count = 0;
foreach ($names as $name) {
$wrapper = $locale_config_manager->get($name);
foreach ($langcodes as $langcode) {
$translation = $wrapper->getValue() ? $wrapper->getTranslation($langcode)->getValue() : NULL;
if ($translation) {
$locale_config_manager->saveTranslationData($name, $langcode, $translation);
$count++;
}
else {
// Do not bother deleting language overrides which do not exist in the
// first place.
if (!$language_manager->getLanguageConfigOverride($langcode, $name)->isNew()) {
$locale_config_manager->deleteTranslationData($name, $langcode);
}
}
}
}
return $count;
}
......@@ -24,6 +24,7 @@
use Drupal\Core\Language\LanguageInterface;
use Drupal\language\ConfigurableLanguageInterface;
use Drupal\Component\Utility\Crypt;
use Drupal\locale\Locale;
/**
* Regular expression pattern used to localize JavaScript strings.
......@@ -226,7 +227,7 @@ function locale_configurable_language_delete(ConfigurableLanguageInterface $lang
locale_translate_delete_translation_files(array(), array($language->id()));
// Remove translated configuration objects.
\Drupal\locale\Locale::config()->deleteLanguageTranslations($language->id());
Locale::config()->deleteLanguageTranslations($language->id());
// Changing the language settings impacts the interface:
_locale_invalidate_js($language->id());
......@@ -246,7 +247,7 @@ function locale_configurable_language_delete(ConfigurableLanguageInterface $lang
*/
function locale_translatable_language_list() {
$languages = \Drupal::languageManager()->getLanguages();
if (!locale_translate_english()) {
if (!locale_is_translatable('en')) {
unset($languages['en']);
}
return $languages;
......@@ -312,6 +313,8 @@ function locale_get_plural($count, $langcode = NULL) {
* Implements hook_modules_installed().
*/
function locale_modules_installed($modules) {
locale_system_set_config_langcodes();
$components['module'] = $modules;
locale_system_update($components);
}
......@@ -328,6 +331,8 @@ function locale_module_preuninstall($module) {
* Implements hook_themes_installed().
*/
function locale_themes_installed($themes) {
locale_system_set_config_langcodes();
$components['theme'] = $themes;
locale_system_update($components);
}
......@@ -355,6 +360,34 @@ function locale_cron() {
}
}
/**
* Updates default configuration when new modules or themes are installed.
*/
function locale_system_set_config_langcodes() {
// Need to rewrite some default configuration language codes if the default
// site language is not English.
$default_langcode = \Drupal::languageManager()->getDefaultLanguage()->getId();
if ($default_langcode != 'en') {
// Update active configuration copies of all prior shipped configuration if
// they are still English. It is not enough to change configuration shipped
// with the components just installed, because installing a component such
// as views or tour module may bring in default configuration from prior
// components.
$names = Locale::config()->getComponentNames();
foreach ($names as $name) {
$config = \Drupal::configFactory()->reset($name)->getEditable($name);
// Should only update if still exists in active configuration. If locale
// module is enabled later, then some configuration may not exist anymore.
if (!$config->isNew()) {
$langcode = $config->get('langcode');
if (empty($langcode) || $langcode == 'en') {
$config->set('langcode', $default_langcode)->save();
}
}
}
}
}
/**
* Imports translations when new modules or themes are installed.
*
......@@ -411,8 +444,6 @@ function locale_system_remove($components) {
if ($language_list = locale_translatable_language_list()) {
module_load_include('compare.inc', 'locale');
\Drupal::moduleHandler()->loadInclude('locale', 'bulk.inc');
// Delete configuration translations.
\Drupal\locale\Locale::config()->deleteComponentTranslations($components, array_keys($language_list));
// Only when projects are removed, the translation files and records will be
// deleted. Not each disabled module will remove a project, e.g., sub
......@@ -606,7 +637,7 @@ function locale_form_language_admin_overview_form_alter(&$form, FormStateInterfa
'translated' => 0,
'ratio' => 0,
);
if (!$language->isLocked() && ($langcode != 'en' || locale_translate_english())) {
if (!$language->isLocked() && locale_is_translatable($langcode)) {
$form['languages'][$langcode]['locale_statistics'] = array(
'#markup' => \Drupal::l(
t('@translated/@total (@ratio%)', array(
......@@ -645,21 +676,26 @@ function locale_form_language_admin_add_form_alter(&$form, FormStateInterface $f
* Set a batch for a newly-added language.
*/
function locale_form_language_admin_add_form_alter_submit($form, FormStateInterface $form_state) {
if (\Drupal::config('locale.settings')->get('translation.import_enabled')) {
if ($form_state->isValueEmpty('predefined_langcode') || $form_state->getValue('predefined_langcode') == 'custom') {
$langcode = $form_state->getValue('langcode');
}
else {
$langcode = $form_state->getValue('predefined_langcode');
}
\Drupal::moduleHandler()->loadInclude('locale', 'fetch.inc');
$options = _locale_translation_default_update_options();
if ($form_state->isValueEmpty('predefined_langcode') || $form_state->getValue('predefined_langcode') == 'custom') {
$langcode = $form_state->getValue('langcode');
}
else {
$langcode = $form_state->getValue('predefined_langcode');
}
if (\Drupal::config('locale.settings')->get('translation.import_enabled')) {
// Download and import translations for the newly added language.
module_load_include('fetch.inc', 'locale');
$options = _locale_translation_default_update_options();
$batch = locale_translation_batch_update_build(array(), array($langcode), $options);
batch_set($batch);
}
// Create or update all configuration translations for this language.
// Create or update all configuration translations for this language. If we
// are adding English then we need to run this even if import is not enabled,
// because then we extract English sources from shipped configuration.
if (\Drupal::config('locale.settings')->get('translation.import_enabled') || $langcode == 'en') {
\Drupal::moduleHandler()->loadInclude('locale', 'bulk.inc');
if ($batch = locale_config_batch_update_components($options, array($langcode))) {
batch_set($batch);
......@@ -689,13 +725,16 @@ function locale_form_language_admin_edit_form_alter_submit($form, FormStateInter
}
/**
* Checks whether locale translates to English.
* Checks whether $langcode is a language supported as a locale target.
*
* @param string $langcode
* The language code.
*
* @return bool
* Returns TRUE if content should be translated to English, FALSE otherwise.
* Whether $langcode can be translated to in locale.
*/
function locale_translate_english() {
return \Drupal::config('locale.settings')->get('translate_english');
function locale_is_translatable($langcode) {
return $langcode != 'en' || \Drupal::config('locale.settings')->get('translate_english');
}
/**
......@@ -1020,19 +1059,14 @@ function _locale_refresh_translations($langcodes, $lids = array()) {
/**
* Refreshes configuration after string translations have been updated.
*
* The information that will be refreshed includes:
* - JavaScript translations.
* - Locale cache.
*
* @param array $langcodes
* Language codes for updated translations.
* @param array $lids
* List of string identifiers that have been updated / created.
*/
function _locale_refresh_configuration(array $langcodes, array $lids) {
if ($lids && $langcodes && $names = \Drupal\locale\Locale::config()->getStringNames($lids)) {
\Drupal::moduleHandler()->loadInclude('locale', 'bulk.inc');
locale_config_update_multiple($names, $langcodes);
if ($lids && $langcodes && $names = Locale::config()->getStringNames($lids)) {
Locale::config()->updateConfigTranslations($names, $langcodes);
}
}
......
services:
locale.config.typed:
locale.config_manager:
class: Drupal\locale\LocaleConfigManager
arguments: ['@config.storage', '@config.storage.installer', '@locale.storage', '@config.factory', '@config.typed', '@language_manager']
locale.storage:
......@@ -22,6 +22,6 @@ services:
- { name: stream_wrapper, scheme: translations }
locale.config_subscriber:
class: Drupal\locale\LocaleConfigSubscriber
arguments: ['@locale.storage', '@config.factory', '@locale.config.typed']
arguments: ['@config.factory', '@locale.config_manager']
tags:
- { name: event_subscriber }
......@@ -61,7 +61,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
$languages = $this->languageManager->getLanguages();
$language_options = array();
foreach ($languages as $langcode => $language) {
if ($langcode != 'en' || locale_translate_english()) {
if (locale_is_translatable($langcode)) {
$language_options[$langcode] = $language->getName();
}
}
......
......@@ -79,7 +79,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
// are to translate Drupal to English as well.
$existing_languages = array();
foreach ($languages as $langcode => $language) {
if ($langcode != 'en' || locale_translate_english()) {
if (locale_is_translatable($langcode)) {
$existing_languages[$langcode] = $language->getName();
}
}
......
......@@ -164,7 +164,7 @@ protected function translateFilters() {
$languages = $this->languageManager->getLanguages();
$language_options = array();
foreach ($languages as $langcode => $language) {
if ($langcode != 'en' || locale_translate_english()) {
if (locale_is_translatable($langcode)) {
$language_options[$langcode] = $language->getName();
}
}
......
......@@ -23,6 +23,6 @@ class Locale {
* @return \Drupal\locale\LocaleConfigManager
*/
public static function config() {
return \Drupal::service('locale.config.typed');
return \Drupal::service('locale.config_manager');
}
}
<?php
/**
* @file
* Contains \Drupal\locale\LocaleTypedConfig.
*/
namespace Drupal\locale;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\TypedData\ContextAwareInterface;
use Drupal\Core\TypedData\DataDefinitionInterface;
use Drupal\Core\Config\Schema\Element;
use Drupal\Core\Config\TypedConfigManagerInterface;
use Drupal\Core\TypedData\TraversableTypedDataInterface;
use Drupal\Core\TypedData\TypedDataInterface;
/**
* Defines the locale configuration wrapper object.
*/
class LocaleTypedConfig extends Element {