diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 5b8553d319088c70209a862692d6b33fec4d5dac..d9f44daaeb575f599e566c6c59a7510ef8d12965 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -2409,8 +2409,10 @@ function language($type) {
* name and its value is its configurability (TRUE/FALSE).
*/
function language_types_get_all() {
- return array_keys(variable_get('language_types', language_types_get_default()));
+ $types = \Drupal::config('system.language.types')->get('all');
+ return $types ? $types : array_keys(language_types_get_default());
}
+
/**
* Returns a list of the built-in language types.
*
diff --git a/core/includes/language.inc b/core/includes/language.inc
index 976dd7539b4a8ba14e8d7beaafddb6bcbbe830fd..5f7d823863593df3a61df152182cfb2dc2355209 100644
--- a/core/includes/language.inc
+++ b/core/includes/language.inc
@@ -14,6 +14,11 @@
*/
const LANGUAGE_NEGOTIATION_SELECTED = 'language-selected';
+/**
+ * The language is determined using the current interface language.
+ */
+const LANGUAGE_NEGOTIATION_INTERFACE = 'language-interface';
+
/**
* @defgroup language_negotiation Language Negotiation API functionality
* @{
@@ -52,6 +57,10 @@
* }
* @endcode
*
+ * The locked configuration property prevents one language type from being
+ * switched from customized to not customized, and vice versa.
+ * @see language_types_set()
+ *
* Every language type can have a different set of language negotiation methods
* assigned to it. Different language types often share the same language
* negotiation settings, but they can have independent settings if needed. If
@@ -167,35 +176,12 @@ function language_types_info() {
* whose language negotiation methods are module-defined and not altered through
* the user interface.
*
- * @param $stored
- * (optional) By default, retrieves values from the 'language_types' variable
- * to avoid unnecessary hook invocations. If set to FALSE, retrieves values
- * from the actual language type definitions. This allows reaction to
- * alterations performed on the definitions by modules installed after the
- * 'language_types' variable is set.
- *
* @return
* An array of language type names.
*/
-function language_types_get_configurable($stored = TRUE) {
- $configurable = &drupal_static(__FUNCTION__);
-
- if ($stored && !isset($configurable)) {
- $types = variable_get('language_types', language_types_get_default());
- $configurable = array_keys(array_filter($types));
- }
-
- if (!$stored) {
- $result = array();
- foreach (language_types_info() as $type => $info) {
- if (!isset($info['fixed'])) {
- $result[] = $type;
- }
- }
- return $result;
- }
-
- return $configurable;
+function language_types_get_configurable() {
+ $configurable = Drupal::config('system.language.types')->get('configurable');
+ return $configurable ? $configurable : array();
}
/**
@@ -205,48 +191,70 @@ function language_types_get_configurable($stored = TRUE) {
* An array of language types.
*/
function language_types_disable($types) {
- $enabled_types = variable_get('language_types', language_types_get_default());
-
- foreach ($types as $type) {
- unset($enabled_types[$type]);
- }
-
- variable_set('language_types', $enabled_types);
+ $configurable = language_types_get_configurable();
+ config('system.language.types')->set('configurable', array_diff($configurable, $types))->save();
}
/**
* Updates the language type configuration.
+ *
+ * @param array $configurable_language_types
+ * An array of configurable language types.
*/
-function language_types_set() {
+function language_types_set(array $configurable_language_types) {
// Ensure that we are getting the defined language negotiation information. An
// invocation of module_enable() or module_disable() could outdate the cached
// information.
drupal_static_reset('language_types_info');
drupal_static_reset('language_negotiation_info');
- // Determine which language types are configurable and which not by checking
- // whether the 'fixed' key is defined. Non-configurable (fixed) language types
- // have their language negotiation settings stored there.
$language_types = array();
$negotiation_info = language_negotiation_info();
- foreach (language_types_info() as $type => $info) {
- if (isset($info['fixed'])) {
- $language_types[$type] = FALSE;
- $method_weights = array();
- foreach ($info['fixed'] as $weight => $method_id) {
- if (isset($negotiation_info[$method_id])) {
- $method_weights[$method_id] = $weight;
- }
+ $language_types_info = language_types_info();
+
+ foreach ($language_types_info as $type => $info) {
+ $configurable = in_array($type, $configurable_language_types);
+
+ // Check whether the language type is unlocked. Only the status of unlocked
+ // language types can be toggled between configurable and non-configurable.
+ // The default language negotiation settings, if available, are stored in
+ // $info['fixed'].
+ if (empty($info['locked'])) {
+ // If we have a non-locked non-configurable language type without default
+ // language negotiation settings, we use the values negotiated for the
+ // interface language which should always be available.
+ if (!$configurable && !empty($info['fixed'])) {
+ $method_weights = array(LANGUAGE_NEGOTIATION_INTERFACE);
+ $method_weights = array_flip($method_weights);
+ language_negotiation_set($type, $method_weights);
}
- language_negotiation_set($type, $method_weights);
}
else {
- $language_types[$type] = TRUE;
+ // Locked language types with default settings are always considered
+ // non-configurable. In turn if default settings are missing, the language
+ // type is always considered configurable.
+ $configurable = empty($info['fixed']);
+
+ // If the language is non-configurable we need to store its language
+ // negotiation settings.
+ if (!$configurable) {
+ $method_weights = array();
+ foreach ($info['fixed'] as $weight => $method_id) {
+ if (isset($negotiation_info[$method_id])) {
+ $method_weights[$method_id] = $weight;
+ }
+ }
+ language_negotiation_set($type, $method_weights);
+ }
}
+
+ $language_types[$type] = $configurable;
}
- // Save enabled language types.
- variable_set('language_types', $language_types);
+ // Store the language type configuration.
+ $config = config('system.language.types');
+ $config->set('configurable', array_keys(array_filter($language_types)))->save();
+ $config->set('all', array_keys($language_types))->save();
// Ensure that subsequent calls of language_types_get_configurable() return
// the updated language type information.
@@ -367,7 +375,7 @@ function language_negotiation_set($type, $method_weights) {
$negotiation = array();
$negotiation_info = language_negotiation_info();
- $default_types = language_types_get_configurable(FALSE);
+ $default_types = language_types_get_configurable();
// Order the language negotiation method list by weight.
asort($method_weights);
diff --git a/core/includes/update.inc b/core/includes/update.inc
index c11476b12aea30cba4c6a3b4c43fd8b19f859ab2..cf25b03bef52a14a4297cfd2b8c5854201bbabf9 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -448,15 +448,20 @@ function update_prepare_d8_bootstrap() {
* Fixes stored include paths to match the "/core" migration.
*/
function update_prepare_stored_includes() {
+ // Retrieve the currently stored language types. Default to the hardcoded D7
+ // values.
+ $default_language_types = array('language' => TRUE, 'language_content' => FALSE, 'language_url' => FALSE);
+ $language_types = array_keys(update_variable_get('language_types', $default_language_types));
+
// Update language negotiation settings.
- foreach (language_types_get_all() as $language_type) {
- $negotiation = variable_get("language_negotiation_$language_type", array());
+ foreach ($language_types as $language_type) {
+ $negotiation = update_variable_get("language_negotiation_$language_type", array());
foreach ($negotiation as &$method) {
if (isset($method['file']) && $method['file'] == 'includes/locale.inc') {
$method['file'] = 'core/modules/language/language.negotiation.inc';
}
}
- variable_set("language_negotiation_$language_type", $negotiation);
+ update_variable_set("language_negotiation_$language_type", $negotiation);
}
}
diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php
index d13f6f6542e59c66626e5c948f1926ac629520b2..a17ea10a438d970fbe20034824cf188fa11fcb94 100644
--- a/core/lib/Drupal/Core/Language/LanguageManager.php
+++ b/core/lib/Drupal/Core/Language/LanguageManager.php
@@ -146,7 +146,7 @@ public function isMultilingual() {
* An array of all language types.
*/
protected function getLanguageTypes() {
- return array_keys(variable_get('language_types', language_types_get_default()));
+ return language_types_get_all();
}
/**
diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module
index cbd33e8915d05bd7db9b8f0a43c76549be175305..3dc5c3c6810015da9ea32aaf26fa95c5e7cdc711 100644
--- a/core/modules/content_translation/content_translation.module
+++ b/core/modules/content_translation/content_translation.module
@@ -64,8 +64,9 @@ function content_translation_module_implements_alter(&$implementations, $hook) {
* Implements hook_language_type_info_alter().
*/
function content_translation_language_types_info_alter(array &$language_types) {
- // Make content language negotiation configurable by removing its predefined
- // configuration.
+ // Make content language negotiation configurable by removing the 'locked'
+ // flag.
+ $language_types[Language::TYPE_CONTENT]['locked'] = FALSE;
unset($language_types[Language::TYPE_CONTENT]['fixed']);
}
diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc
index a7c6663d7628f22e30e9d9ea291120b649e8332b..aca69111c33a20f135782f026dbbc172fca8d0f3 100644
--- a/core/modules/language/language.admin.inc
+++ b/core/modules/language/language.admin.inc
@@ -358,11 +358,17 @@ function language_negotiation_configure_form() {
$form = array(
'#submit' => array('language_negotiation_configure_form_submit'),
'#theme' => 'language_negotiation_configure_form',
- '#language_types' => language_types_get_configurable(FALSE),
'#language_types_info' => language_types_info(),
'#language_negotiation_info' => language_negotiation_info(),
);
-
+ $form['#language_types'] = array();
+ $configurable = config('system.language.types')->get('configurable');
+ foreach ($form['#language_types_info'] as $type => $info) {
+ // Show locked language types only if they are configurable.
+ if (empty($info['locked']) || in_array($type, $configurable)) {
+ $form['#language_types'][] = $type;
+ }
+ }
foreach ($form['#language_types'] as $type) {
language_negotiation_configure_form_table($form, $type);
}
@@ -390,6 +396,21 @@ function language_negotiation_configure_form_table(&$form, $type) {
'#show_operations' => FALSE,
'weight' => array('#tree' => TRUE),
);
+ // Only show configurability checkbox for the unlocked language types.
+ if (empty($info['locked'])) {
+ $configurable = config('system.language.types')->get('configurable');
+ $table_form['configurable'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Customize %language_name language detection to differ from User interface text language detection settings.', array('%language_name' => $info['name'])),
+ '#default_value' => in_array($type, $configurable),
+ '#attributes' => array('class' => array('language-customization-checkbox')),
+ '#attached' => array(
+ 'library' => array(
+ array('language', 'language.admin')
+ ),
+ ),
+ );
+ }
$negotiation_info = $form['#language_negotiation_info'];
$enabled_methods = variable_get("language_negotiation_$type", array());
@@ -521,12 +542,13 @@ function theme_language_negotiation_configure_form($variables) {
'#rows' => $rows,
'#attributes' => array('id' => "language-negotiation-methods-$type"),
);
- $table = drupal_render($build);
+ $table = drupal_render($form[$type]['configurable']);
+ $table .= drupal_render($build);
$table .= drupal_render_children($form[$type]);
drupal_add_tabledrag("language-negotiation-methods-$type", 'order', 'sibling', "language-method-weight-$type");
- $output .= '
' . $title . $description . $table . '
';
+ $output .= '' . $title . $description . $table . '
';
}
$output .= drupal_render_children($form);
@@ -539,11 +561,19 @@ function theme_language_negotiation_configure_form($variables) {
function language_negotiation_configure_form_submit($form, &$form_state) {
$configurable_types = $form['#language_types'];
+ $stored_values = config('system.language.types')->get('configurable');
+ $customized = array();
+ $method_weights_type = array();
+
foreach ($configurable_types as $type) {
+ $customized[$type] = in_array($type, $stored_values);
$method_weights = array();
$enabled_methods = $form_state['values'][$type]['enabled'];
$enabled_methods[LANGUAGE_NEGOTIATION_SELECTED] = TRUE;
$method_weights_input = $form_state['values'][$type]['weight'];
+ if (isset($form_state['values'][$type]['configurable'])) {
+ $customized[$type] = !empty($form_state['values'][$type]['configurable']);
+ }
foreach ($method_weights_input as $method_id => $weight) {
if ($enabled_methods[$method_id]) {
@@ -551,13 +581,28 @@ function language_negotiation_configure_form_submit($form, &$form_state) {
}
}
- language_negotiation_set($type, $method_weights);
+ $method_weights_type[$type] = $method_weights;
variable_set("language_negotiation_methods_weight_$type", $method_weights_input);
}
// Update non-configurable language types and the related language negotiation
// configuration.
- language_types_set();
+ language_types_set(array_keys(array_filter($customized)));
+
+ // Update the language negotiations after setting the configurability.
+ foreach ($method_weights_type as $type => $method_weights) {
+ language_negotiation_set($type, $method_weights);
+ }
+
+ // Clear block definitions cache since the available blocks and their names
+ // may have been changed based on the configurable types.
+ if (module_exists('block')) {
+ // If there is an active language switcher for a language type that has been
+ // made not configurable, deactivate it first.
+ $non_configurable = array_keys(array_diff($customized, array_filter($customized)));
+ _language_disable_language_switcher($non_configurable);
+ Drupal::service('plugin.manager.block')->clearCachedDefinitions();
+ }
$form_state['redirect'] = 'admin/config/regional/language/detection';
drupal_set_message(t('Language negotiation configuration saved.'));
@@ -582,10 +627,8 @@ function language_negotiation_configure_browser_form($form, &$form_state) {
// the list of existing and then predefined languages.
if (empty($existing_languages)) {
$language_options = language_admin_predefined_list();
- $default = key($language_options);
}
else {
- $default = key($existing_languages);
$language_options = array(
t('Existing languages') => $existing_languages,
t('Languages not yet added') => language_admin_predefined_list()
@@ -941,3 +984,21 @@ function language_content_settings_form_submit(array $form, array &$form_state)
}
drupal_set_message(t('Settings successfully updated.'));
}
+
+/**
+ * Helper function to disable the language switcher blocks.
+ *
+ * @param array $language_types
+ * Array containing all language types whose language switchers need to be
+ * disabled.
+ */
+function _language_disable_language_switcher(array $language_types) {
+ $blocks = _block_rehash();
+ foreach ($language_types as $language_type) {
+ foreach ($blocks as $block) {
+ if (strpos($block->id, 'language_switcher_' . substr($language_type, 9)) !== FALSE) {
+ $block->delete();
+ }
+ }
+ }
+}
diff --git a/core/modules/language/language.admin.js b/core/modules/language/language.admin.js
new file mode 100644
index 0000000000000000000000000000000000000000..41623cfa4027f2d5e175e353d5d701b625a2243b
--- /dev/null
+++ b/core/modules/language/language.admin.js
@@ -0,0 +1,32 @@
+(function ($, Drupal) {
+
+"use strict";
+
+/**
+ * Makes language negotiation inherit user interface negotiation.
+ */
+Drupal.behaviors.negotiationLanguage = {
+ attach: function () {
+ var $configForm = $('#language-negotiation-configure-form');
+ var inputSelector = 'input[name$="[configurable]"]';
+ // Given a customization checkbox derive the language type being changed.
+ function toggleTable (checkbox) {
+ var $checkbox = $(checkbox);
+ // Get the language detection type such as User interface text language
+ // detection or Content language detection.
+ $checkbox.closest('.table-language-group')
+ .find('table, .tabledrag-toggle-weight')
+ .toggle($checkbox.prop('checked'));
+ }
+ // Bind hide/show and rearrange customization checkboxes.
+ $configForm.once('negotiation-language-admin-bind').on('change', inputSelector, function (event) {
+ toggleTable(event.target);
+ });
+ // Initially, hide language detection types that are not customized.
+ $configForm.find(inputSelector + ':not(:checked)').each(function (index, element) {
+ toggleTable(element);
+ });
+ }
+};
+
+})(jQuery, Drupal);
diff --git a/core/modules/language/language.install b/core/modules/language/language.install
index 066ef2665be7c0119d177987cbc13d6c8ab5b412..b7b3c770108e910c03958b054bbec9a083badfc2 100644
--- a/core/modules/language/language.install
+++ b/core/modules/language/language.install
@@ -17,7 +17,8 @@
function language_install() {
// Enable URL language detection for each configurable language type.
require_once DRUPAL_ROOT . '/core/includes/language.inc';
- foreach (language_types_get_configurable(FALSE) as $type) {
+ foreach (language_types_get_configurable() as $type) {
+ module_load_include('inc', 'language', 'language.negotiation');
language_negotiation_set($type, array(LANGUAGE_NEGOTIATION_URL => 0));
}
}
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index bdbd15ce2ca494929087617c71f016c7362ea07b..b26105f2b1f696a12a0a63e6888f556505207270 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -590,6 +590,26 @@ function language_delete($langcode) {
return FALSE;
}
+/**
+ * Implements hook_library_info().
+ */
+function language_library_info() {
+ $libraries['language.admin'] = array(
+ 'title' => 'Language detection admin',
+ 'version' => VERSION,
+ 'js' => array(
+ drupal_get_path('module', 'language') . '/language.admin.js' => array(),
+ ),
+ 'dependencies' => array(
+ array('system', 'jquery'),
+ array('system', 'drupal'),
+ array('system', 'jquery.once'),
+ ),
+ );
+
+ return $libraries;
+}
+
/**
* Implements hook_language_types_info().
*
@@ -611,14 +631,17 @@ function language_language_types_info() {
Language::TYPE_INTERFACE => array(
'name' => t('User interface text'),
'description' => t('Order of language detection methods for user interface text. If a translation of user interface text is available in the detected language, it will be displayed.'),
+ 'locked' => TRUE,
),
Language::TYPE_CONTENT => array(
'name' => t('Content'),
'description' => t('Order of language detection methods for content. If a version of content is available in the detected language, it will be displayed.'),
'fixed' => array(LANGUAGE_NEGOTIATION_INTERFACE),
+ 'locked' => TRUE,
),
Language::TYPE_URL => array(
'fixed' => array(LANGUAGE_NEGOTIATION_URL, LANGUAGE_NEGOTIATION_URL_FALLBACK),
+ 'locked' => TRUE,
),
);
}
@@ -717,8 +740,9 @@ function language_negotiation_include() {
* Implements hook_modules_enabled().
*/
function language_modules_enabled($modules) {
- language_negotiation_include();
- language_types_set();
+ include_once DRUPAL_ROOT . '/core/includes/language.inc';
+ // Load configurability options from configuration.
+ language_types_set(array());
language_negotiation_purge();
}
diff --git a/core/modules/language/language.negotiation.inc b/core/modules/language/language.negotiation.inc
index c4e97b377ab6fcabe806f936e602e26645af6673..78b9d27b755092a7ff9eb63d9d59266e048c7967 100644
--- a/core/modules/language/language.negotiation.inc
+++ b/core/modules/language/language.negotiation.inc
@@ -19,11 +19,6 @@
*/
const LANGUAGE_NEGOTIATION_BROWSER = 'language-browser';
-/**
- * The language is determined using the current interface language.
- */
-const LANGUAGE_NEGOTIATION_INTERFACE = 'language-interface';
-
/**
* If no URL language, language is determined using an already detected one.
*/
diff --git a/core/modules/language/lib/Drupal/language/Plugin/Derivative/LanguageBlock.php b/core/modules/language/lib/Drupal/language/Plugin/Derivative/LanguageBlock.php
index ee52336870429793b2d206c7d03b8433260c4a09..a329c3b1954bd6f66d4a400bc382d2cedf3c2050 100644
--- a/core/modules/language/lib/Drupal/language/Plugin/Derivative/LanguageBlock.php
+++ b/core/modules/language/lib/Drupal/language/Plugin/Derivative/LanguageBlock.php
@@ -19,11 +19,17 @@ class LanguageBlock extends DerivativeBase {
public function getDerivativeDefinitions(array $base_plugin_definition) {
include_once DRUPAL_ROOT . '/core/includes/language.inc';
$info = language_types_info();
- foreach (language_types_get_configurable(FALSE) as $type) {
+ $configurable_types = language_types_get_configurable();
+ foreach ($configurable_types as $type) {
$this->derivatives[$type] = $base_plugin_definition;
$this->derivatives[$type]['admin_label'] = t('Language switcher (!type)', array('!type' => $info[$type]['name']));
$this->derivatives[$type]['cache'] = DRUPAL_NO_CACHE;
}
+ // If there is just one configurable type then change the title of the
+ // block.
+ if (count($configurable_types) == 1) {
+ $this->derivatives[reset($configurable_types)]['admin_label'] = t('Language switcher');
+ }
return parent::getDerivativeDefinitions($base_plugin_definition);
}
}
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php
index e580e5cf84ae275badfe792aedd630f73cb488cf..6ab71ba69d4ffd181554032f3499baf84a78a138 100644
--- a/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php
@@ -56,8 +56,8 @@ function testInfoAlterations() {
\Drupal::state()->set('language_test.content_language_type', TRUE);
$this->languageNegotiationUpdate();
$type = Language::TYPE_CONTENT;
- $language_types = variable_get('language_types', language_types_get_default());
- $this->assertTrue($language_types[$type], 'Content language type is configurable.');
+ $language_types = language_types_get_configurable();
+ $this->assertTrue(in_array($type, $language_types), 'Content language type is configurable.');
// Enable some core and custom language negotiation methods. The test
// language type is supposed to be configurable.
@@ -69,6 +69,7 @@ function testInfoAlterations() {
$form_field => TRUE,
$type . '[enabled][' . $test_method_id . ']' => TRUE,
$test_type . '[enabled][' . $test_method_id . ']' => TRUE,
+ $test_type . '[configurable]' => TRUE,
);
$this->drupalPost('admin/config/regional/language/detection', $edit, t('Save settings'));
@@ -98,7 +99,7 @@ function testInfoAlterations() {
foreach (language_types_get_all() as $type) {
$langcode = $last[$type];
$value = $type == Language::TYPE_CONTENT || strpos($type, 'test') !== FALSE ? 'it' : 'en';
- $this->assertEqual($langcode, $value, format_string('The negotiated language for %type is %language', array('%type' => $type, '%language' => $langcode)));
+ $this->assertEqual($langcode, $value, format_string('The negotiated language for %type is %language', array('%type' => $type, '%language' => $value)));
}
// Disable language_test and check that everything is set back to the
@@ -158,8 +159,9 @@ protected function languageNegotiationUpdate($op = 'enable') {
*/
protected function checkFixedLanguageTypes() {
drupal_static_reset('language_types_info');
+ $configurable = language_types_get_configurable();
foreach (language_types_info() as $type => $info) {
- if (isset($info['fixed'])) {
+ if (!in_array($type, $configurable) && isset($info['fixed'])) {
$negotiation = variable_get("language_negotiation_$type", array());
$equal = count($info['fixed']) == count($negotiation);
while ($equal && list($id) = each($negotiation)) {
diff --git a/core/modules/language/tests/language_test/language_test.module b/core/modules/language/tests/language_test/language_test.module
index 3cb6f6bd529802b8fefc7f7d6bdb7e285b1afac9..267cdf32b87130eeeb9f320c7952328effafffcf 100644
--- a/core/modules/language/tests/language_test/language_test.module
+++ b/core/modules/language/tests/language_test/language_test.module
@@ -32,6 +32,7 @@ function language_test_language_types_info() {
),
'fixed_test_language_type' => array(
'fixed' => array('test_language_negotiation_method'),
+ 'locked' => TRUE,
),
);
}
@@ -42,7 +43,15 @@ function language_test_language_types_info() {
*/
function language_test_language_types_info_alter(array &$language_types) {
if (Drupal::state()->get('language_test.content_language_type')) {
+ $language_types[Language::TYPE_CONTENT]['locked'] = FALSE;
unset($language_types[Language::TYPE_CONTENT]['fixed']);
+ // By default languages are not configurable. Make Language::TYPE_CONTENT
+ // configurable.
+ $configurable = config('system.language.types')->get('configurable');
+ if (!in_array(Language::TYPE_CONTENT, $configurable)) {
+ $configurable[] = Language::TYPE_CONTENT;
+ config('system.language.types')->set('configurable', $configurable)->save();
+ }
}
}
@@ -87,6 +96,7 @@ function language_test_language_negotiation_info_alter(array &$negotiation_info)
*/
function language_test_store_language_negotiation() {
$last = array();
+ print_r(language_types_get_all());
foreach (language_types_get_all() as $type) {
$last[$type] = language($type)->id;
}
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php
index c53ed7a03c423b9d2c1383415d46ffcedf2cb5a0..961a5dd58b2a48553ebda07122f63c0d96332d3a 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php
@@ -96,7 +96,7 @@ function testUninstallProcess() {
// Change language negotiation options.
drupal_load('module', 'locale');
- variable_set('language_types', language_types_get_default() + array('language_custom' => TRUE));
+ \Drupal::config('system.language.types')->set('configurable', language_types_get_default() + array('language_custom' => TRUE))->save();
variable_set('language_negotiation_' . Language::TYPE_INTERFACE, language_language_negotiation_info());
variable_set('language_negotiation_' . Language::TYPE_CONTENT, language_language_negotiation_info());
variable_set('language_negotiation_' . Language::TYPE_URL, language_language_negotiation_info());
diff --git a/core/modules/system/config/system.language.types.yml b/core/modules/system/config/system.language.types.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2b77d89967f0bc8b0d08da00d5d7fc4ff050bf48
--- /dev/null
+++ b/core/modules/system/config/system.language.types.yml
@@ -0,0 +1,6 @@
+all:
+ - language_interface
+ - language_content
+ - language_url
+configurable:
+ - language_interface
diff --git a/core/modules/system/language.api.php b/core/modules/system/language.api.php
index d01df59174e449147c762df6c0c97baeedaacbc5..9fe910acf3540e0a99a08d4fd31705c732e05d6f 100644
--- a/core/modules/system/language.api.php
+++ b/core/modules/system/language.api.php
@@ -44,10 +44,16 @@ function hook_language_switch_links_alter(array &$links, $type, $path) {
* may contain the following elements:
* - name: The human-readable language type identifier.
* - description: A description of the language type.
+ * - locked: A boolean indicating if the user can choose wether to configure
+ * the language type or not using the UI.
* - fixed: A fixed array of language negotiation method identifiers to use to
- * initialize this language. Defining this key makes the language type
- * non-configurable, so it will always use the specified methods in the
- * given priority order. Omit to make the language type configurable.
+ * initialize this language. If locked is set to TRUE and fixed is set, it
+ * will always use the specified methods in the given priority order. If not
+ * present and locked is TRUE then LANGUAGE_NEGOTIATION_INTERFACE will be
+ * used.
+ *
+ * @todo Rename the 'fixed' key to something more meaningful, for instance
+ * 'negotiation settings'.
*
* @see hook_language_types_info_alter()
* @ingroup language_negotiation
@@ -57,8 +63,10 @@ function hook_language_types_info() {
'custom_language_type' => array(
'name' => t('Custom language'),
'description' => t('A custom language type.'),
+ 'locked' => FALSE,
),
'fixed_custom_language_type' => array(
+ 'locked' => TRUE,
'fixed' => array('custom_language_negotiation_method'),
),
);
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php
index 099d911a45c1cdfb209ea79e3e63834509c38bb9..5a1d3f6ef45dbc22e41d835732b76f47cc616f03 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php
@@ -543,7 +543,7 @@ function testGetLibrary() {
$this->assertTrue(isset($libraries['jquery.farbtastic']), 'Retrieved all module libraries.');
// Retrieve all libraries for a module not implementing hook_library_info().
// Note: This test installs language module.
- $libraries = drupal_get_library('language');
+ $libraries = drupal_get_library('dblog');
$this->assertEqual($libraries, array(), 'Retrieving libraries from a module not implementing hook_library_info() returns an emtpy array.');
// Retrieve a specific library by module and name.
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index f10d86b2dbaccf9da58880d40855721477b0e5d5..89f9ddc7294d716a2ab749b6d41387bc34ce1a52 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -2240,6 +2240,19 @@ function system_update_8058() {
}
+/**
+ * Move variable language_types to config.
+ *
+ * @ingroup config_upgrade
+ */
+function system_update_8059() {
+ update_variables_to_config('system.language.types', array(
+ 'language_interface' => 'configurable.language_interface',
+ 'language_content' => 'configurable.language_content',
+ 'language_url' => 'configurable.language_content',
+ ));
+}
+
/**
* @} End of "defgroup updates-7.x-to-8.x".
* The next series of updates should start at 9000.