diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc old mode 100644 new mode 100755 index 906a7c1..3f65758 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -236,6 +236,11 @@ const LANGUAGE_LOCKED = 2; const LANGUAGE_ALL = 3; /** + * The language state used when referring to the site default language . + */ +const LANGUAGE_DEFAULT = 4; + +/** * The type of language used to define the content language. */ const LANGUAGE_TYPE_CONTENT = 'language_content'; @@ -2794,6 +2799,15 @@ function language_list($flags = LANGUAGE_CONFIGURABLE) { // default we remove the locked languages, but the caller may request for // those languages to be added as well. $filtered_languages = array(); + + // Add the site's default language if flagged as allowed value. + if ($flags & LANGUAGE_DEFAULT) { + $default = isset($default) ? $default : language_default(); + // Rename the default language. + $default->name = t("Site's default language"); + $filtered_languages['site_default'] = $default; + } + foreach ($languages as $langcode => $language) { if (($language->locked && !($flags & LANGUAGE_LOCKED)) || (!$language->locked && !($flags & LANGUAGE_CONFIGURABLE))) { continue; diff --git a/core/includes/language.inc b/core/includes/language.inc index 2a0defa..436dd57 100644 --- a/core/includes/language.inc +++ b/core/includes/language.inc @@ -408,7 +408,7 @@ function language_negotiation_info() { // Add the default language negotiation method. $negotiation_info[LANGUAGE_NEGOTIATION_DEFAULT] = array( 'callbacks' => array('language' => 'language_from_default'), - 'weight' => 10, + 'weight' => 14, 'name' => t('Default language'), 'description' => t('Use the default site language (@language_name).', array('@language_name' => language_default()->name)), 'config' => 'admin/config/regional/language', diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc old mode 100644 new mode 100755 index af2b3b1..5634dd2 --- a/core/modules/language/language.admin.inc +++ b/core/modules/language/language.admin.inc @@ -519,6 +519,7 @@ function language_negotiation_configure_form_table(&$form, $type) { '#title_display' => 'invisible', '#default_value' => $weight, '#attributes' => array('class' => array("language-method-weight-$type")), + '#delta' => 20, ); $table_form['title'][$method_id] = array('#markup' => $method_name); @@ -815,6 +816,20 @@ function language_negotiation_configure_session_form($form, &$form_state) { } /** + * Builds the selected language negotiation method configuration form. + */ +function language_negotiation_configure_selected_form($form, &$form_state) { + $form['language_negotiation_selected_langcode'] = array( + '#type' => 'language_select', + '#title' => t('Language'), + '#languages' => LANGUAGE_CONFIGURABLE | LANGUAGE_DEFAULT, + '#default_value' => variable_get('language_negotiation_selected_langcode', FALSE), + ); + + return system_settings_form($form); +} + +/** * Builds the browser language negotiation method configuration form. */ function language_negotiation_configure_browser_form($form, &$form_state) { diff --git a/core/modules/language/language.module b/core/modules/language/language.module old mode 100644 new mode 100755 index 5b62382..8257810 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -135,6 +135,14 @@ function language_menu() { 'access arguments' => array('administer languages'), 'file' => 'language.admin.inc', ); + $items['admin/config/regional/language/detection/selected'] = array( + 'title' => 'Selected language detection configuration', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('language_negotiation_configure_selected_form'), + 'access arguments' => array('administer languages'), + 'file' => 'language.admin.inc', + 'type' => MENU_VISIBLE_IN_BREADCRUMB, + ); return $items; } @@ -448,6 +456,15 @@ function language_language_negotiation_info() { 'description' => t('Account administration pages language setting.'), ); + $negotiation_info[LANGUAGE_NEGOTIATION_SELECTED] = array( + 'callbacks' => array('negotiation' => 'language_from_selected'), + 'file' => $file, + 'weight' => 12, + 'name' => t('Selected'), + 'description' => t('Language based on a selected language.'), + 'config' => 'admin/config/regional/language/detection/selected', + ); + return $negotiation_info; } diff --git a/core/modules/language/language.negotiation.inc b/core/modules/language/language.negotiation.inc old mode 100644 new mode 100755 index fa6a517..a5016ee --- a/core/modules/language/language.negotiation.inc +++ b/core/modules/language/language.negotiation.inc @@ -36,6 +36,11 @@ const LANGUAGE_NEGOTIATION_USER = 'language-user'; const LANGUAGE_NEGOTIATION_USER_ADMIN = 'language-user-admin'; /** + * The language is set based on a configured language. + */ +const LANGUAGE_NEGOTIATION_SELECTED = 'language-selected'; + +/** * The language is set based on the request/session parameters. */ const LANGUAGE_NEGOTIATION_SESSION = 'language-session'; @@ -316,6 +321,24 @@ function language_from_url($languages, $request) { } /** + * Identifies language from configuration. + * + * @param $languages + * An array of valid language objects. + * + * @return + * A valid language code on success, FALSE otherwise. + */ +function language_from_selected($languages) { + $langcode = variable_get('language_negotiation_selected_langcode', FALSE); + // Replace the site's default langcode by its real value. + if ($langcode == 'site_default') { + $langcode = language_from_default(); + } + return isset($languages[$langcode]) ? $langcode : FALSE; +} + +/** * Determines the language to be assigned to URLs when none is detected. * * The language negotiation process has a fallback chain that ends with the diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php index 0b87a09..35b1a39 100644 --- a/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php +++ b/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php @@ -140,6 +140,43 @@ class LanguageUILanguageNegotiationTest extends WebTestBase { // Configure URL language rewrite. variable_set('language_negotiation_url_type', LANGUAGE_TYPE_INTERFACE); + // Configure selected language negotiation to use zh-hans. + $edit = array('language_negotiation_selected_langcode' => $langcode); + $this->drupalPost('admin/config/regional/language/detection/selected', $edit, t('Save configuration')); + $test = array( + 'language_negotiation' => array(LANGUAGE_NEGOTIATION_SELECTED, LANGUAGE_NEGOTIATION_DEFAULT), + 'path' => 'admin/config', + 'expect' => $language_string, + 'expected_method_id' => LANGUAGE_NEGOTIATION_SELECTED, + 'http_header' => $http_header_browser_fallback, + 'message' => 'SELECTED > DEFAULT: UI language is switched based on selected language.', + ); + $this->runTest($test); + + // An invalid language is selected. + variable_set('language_negotiation_selected_langcode', NULL); + $test = array( + 'language_negotiation' => array(LANGUAGE_NEGOTIATION_SELECTED, LANGUAGE_NEGOTIATION_DEFAULT), + 'path' => 'admin/config', + 'expect' => $default_string, + 'expected_method_id' => LANGUAGE_NEGOTIATION_DEFAULT, + 'http_header' => $http_header_browser_fallback, + 'message' => 'SELECTED > DEFAULT: UI language is switched based on selected language.', + ); + $this->runTest($test); + + // No selected language is available. + variable_set('language_negotiation_selected_langcode', $langcode_unknown); + $test = array( + 'language_negotiation' => array(LANGUAGE_NEGOTIATION_SELECTED, LANGUAGE_NEGOTIATION_DEFAULT), + 'path' => 'admin/config', + 'expect' => $default_string, + 'expected_method_id' => LANGUAGE_NEGOTIATION_DEFAULT, + 'http_header' => $http_header_browser_fallback, + 'message' => 'SELECTED > DEFAULT: UI language is switched based on selected language.', + ); + $this->runTest($test); + $tests = array( // Default, browser preference should have no influence. array(