elements with the attributes "text" and
- * "xmlurl" set.
- *
- * @todo Move this functionality to a parser.
- *
- * @param $opml
- * The complete contents of an OPML document.
- *
- * @return
- * An array of feeds, each an associative array with a "title" and a "url"
- * element, or NULL if the OPML document failed to be parsed. An empty array
- * will be returned if the document is valid but contains no feeds, as some
- * OPML documents do.
- */
- protected function parseOpml($opml) {
- $feeds = array();
- $xml_parser = drupal_xml_parser_create($opml);
- if (xml_parse_into_struct($xml_parser, $opml, $values)) {
- foreach ($values as $entry) {
- if ($entry['tag'] == 'OUTLINE' && isset($entry['attributes'])) {
- $item = $entry['attributes'];
- if (!empty($item['XMLURL']) && !empty($item['TEXT'])) {
- $feeds[] = array('title' => $item['TEXT'], 'url' => $item['XMLURL']);
- }
- }
- }
- }
- xml_parser_free($xml_parser);
-
- return $feeds;
- }
-
-}
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/FeedParserTest.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/FeedParserTest.php
index 5f4f9f9..caf2e7d 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/FeedParserTest.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/FeedParserTest.php
@@ -100,6 +100,6 @@ function testInvalidFeed() {
// Update the feed. Use the UI to be able to check the message easily.
$this->drupalGet('admin/config/services/aggregator');
$this->clickLink(t('Update items'));
- $this->assertRaw(t('The feed from %title seems to be broken because of error', array('%title' => $feed->label())));
+ $this->assertRaw(t('The feed from %title seems to be broken because of error "%error"', array('%title' => $feed->label(), '%error' => "[curl] 6: Couldn't resolve host 'http' [url] /")));
}
}
diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc
index f59fb38..94271cc 100644
--- a/core/modules/language/language.admin.inc
+++ b/core/modules/language/language.admin.inc
@@ -357,11 +357,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 they are configurable.
+ if (empty($info['locked']) || $configurable[$type]) {
+ $form['#language_types'][] = $type;
+ }
+ }
foreach ($form['#language_types'] as $type) {
language_negotiation_configure_form_table($form, $type);
}
@@ -389,6 +395,19 @@ 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' => !empty($configurable[$type]),
+ '#attributes' => array('class' => array('language-customization-checkbox')),
+ '#attached' => array(
+ 'js' => array(drupal_get_path('module', 'language') . '/language.admin.js' => array('type' => 'file')),
+ ),
+ );
+ }
$negotiation_info = $form['#language_negotiation_info'];
$enabled_methods = variable_get("language_negotiation_$type", array());
@@ -519,12 +538,13 @@ function theme_language_negotiation_configure_form($variables) {
'rows' => $rows,
'attributes' => array('id' => "language-negotiation-methods-$type"),
);
- $table = theme('table', $variables);
+ $table = drupal_render($form[$type]['configurable']);
+ $table .= theme('table', $variables);
$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);
@@ -537,11 +557,16 @@ function theme_language_negotiation_configure_form($variables) {
function language_negotiation_configure_form_submit($form, &$form_state) {
$configurable_types = $form['#language_types'];
+ $configurable = config('system.language.types')->get('configurable');
+
foreach ($configurable_types as $type) {
$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'])) {
+ $configurable[$type] = !empty($form_state['values'][$type]['configurable']);
+ }
foreach ($method_weights_input as $method_id => $weight) {
if ($enabled_methods[$method_id]) {
@@ -555,7 +580,13 @@ function language_negotiation_configure_form_submit($form, &$form_state) {
// Update non-configurable language types and the related language negotiation
// configuration.
- language_types_set();
+ language_types_set($configurable);
+
+ // Clear block definitions cache since the available blocks and their names
+ // may have been changed based on the configurable types.
+ if (module_exists('block')) {
+ drupal_container()->get('plugin.manager.block')->clearCachedDefinitions();
+ }
$form_state['redirect'] = 'admin/config/regional/language/detection';
drupal_set_message(t('Language negotiation configuration saved.'));
diff --git a/core/modules/language/language.admin.js b/core/modules/language/language.admin.js
new file mode 100644
index 0000000..68e4d3e
--- /dev/null
+++ b/core/modules/language/language.admin.js
@@ -0,0 +1,35 @@
+(function ($) {
+
+"use strict";
+
+/**
+ * Makes language negotiation inherit user interface negotiation.
+ */
+Drupal.behaviors.negotiationLanguage = {
+ attach: function (context) {
+ var $context = $(context);
+ // Given a customization checkbox derive the language type being changed.
+ var toggleTable = function ($checkbox) {
+ // Get the language detection type such as User interface text language
+ // detection or Content language detection.
+ var detectiontype = $checkbox.attr('name').replace('[configurable]', '');
+ var $table = $('.table-' + detectiontype + '-wrapper');
+ if ($checkbox.is(':checked')) {
+ $table.find('table, .tabledrag-toggle-weight-wrapper').show();
+ }
+ else {
+ $table.find('table, .tabledrag-toggle-weight-wrapper').hide();
+ }
+ };
+ // Bind hide/show + rearrange to customization checkboxes.
+ $('body').once('negotiation-language-admin-bind').on('click', '#language-negotiation-configure-form :input.language-customization-checkbox', function (e) {
+ toggleTable($(e.target));
+ });
+ // Initially, hide language detection types that are not customized.
+ $('#language-negotiation-configure-form :input.language-customization-checkbox:not(:checked)').each(function (index, element) {
+ toggleTable($(element));
+ });
+ }
+};
+
+})(jQuery);
diff --git a/core/modules/language/language.install b/core/modules/language/language.install
index b16c53b..78d3a36 100644
--- a/core/modules/language/language.install
+++ b/core/modules/language/language.install
@@ -22,7 +22,7 @@ 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) {
language_negotiation_set($type, array(LANGUAGE_NEGOTIATION_URL => 0));
}
}
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index 6bbb5a7..03f04a9 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -607,14 +607,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,
),
);
}
@@ -714,8 +717,9 @@ function language_negotiation_include() {
* Implements hook_modules_enabled().
*/
function language_modules_enabled($modules) {
- language_negotiation_include();
- language_types_set();
+ // Load configurability options from configuration.
+ $configurable = config('system.language.types')->get('configurable');
+ language_types_set($configurable);
language_negotiation_purge();
}
diff --git a/core/modules/language/language.negotiation.inc b/core/modules/language/language.negotiation.inc
index ca41c78..4e29e47 100644
--- a/core/modules/language/language.negotiation.inc
+++ b/core/modules/language/language.negotiation.inc
@@ -18,11 +18,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.
*/
const LANGUAGE_NEGOTIATION_URL_FALLBACK = 'language-url-fallback';
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 d451b27..f5260f9 100644
--- a/core/modules/language/lib/Drupal/language/Plugin/Derivative/LanguageBlock.php
+++ b/core/modules/language/lib/Drupal/language/Plugin/Derivative/LanguageBlock.php
@@ -38,11 +38,17 @@ public function getDerivativeDefinition($derivative_id, array $base_plugin_defin
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 $this->derivatives;
}
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php
index 8aea763..5357139 100644
--- a/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php
@@ -68,6 +68,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'));
@@ -157,8 +158,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 cb97937..0b98ed5 100644
--- a/core/modules/language/tests/language_test/language_test.module
+++ b/core/modules/language/tests/language_test/language_test.module
@@ -30,6 +30,7 @@ function language_test_language_types_info() {
),
'fixed_test_language_type' => array(
'fixed' => array('test_language_negotiation_method'),
+ 'locked' => TRUE,
),
);
}
@@ -40,7 +41,7 @@ function language_test_language_types_info() {
*/
function language_test_language_types_info_alter(array &$language_types) {
if (state()->get('language_test.content_language_type')) {
- unset($language_types[LANGUAGE_TYPE_CONTENT]['fixed']);
+ $language_types[LANGUAGE_TYPE_CONTENT]['locked'] = FALSE;
}
}
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 0000000..a0ed7ac
--- /dev/null
+++ b/core/modules/system/config/system.language.types.yml
@@ -0,0 +1,4 @@
+configurable:
+ language_interface: '1'
+ language_content: '0'
+ language_url: '0'
diff --git a/core/modules/system/language.api.php b/core/modules/system/language.api.php
index 7c7375f..7f5a996 100644
--- a/core/modules/system/language.api.php
+++ b/core/modules/system/language.api.php
@@ -44,10 +44,13 @@ 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.
*
* @see hook_language_types_info_alter()
* @ingroup language_negotiation
@@ -57,8 +60,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/translation_entity/translation_entity.module b/core/modules/translation_entity/translation_entity.module
index e4dca3e..60c59c4 100644
--- a/core/modules/translation_entity/translation_entity.module
+++ b/core/modules/translation_entity/translation_entity.module
@@ -63,9 +63,9 @@ function translation_entity_module_implements_alter(&$implementations, $hook) {
* Implements hook_language_type_info_alter().
*/
function translation_entity_language_types_info_alter(array &$language_types) {
- // Make content language negotiation configurable by removing its predefined
- // configuration.
- unset($language_types[LANGUAGE_TYPE_CONTENT]['fixed']);
+ // Make content language negotiation configurable by removing unsetting the
+ // 'locked' flag.
+ $language_types[LANGUAGE_TYPE_CONTENT]['locked'] = FALSE;
}
/**