diff --git a/core/modules/language/config/language.mappings.yml b/core/modules/language/config/language.mappings.yml new file mode 100644 index 0000000..913714e --- /dev/null +++ b/core/modules/language/config/language.mappings.yml @@ -0,0 +1,7 @@ +zh-tw: zh-hant-tw +zh-hk: zh-hant-hk +zh-mo: zh-hant-mo +zh-cht: zh-hant +zh-cn: zh-hans-cn +zh-sg: zh-hans-sg +zh-chs: zh-hans diff --git a/core/modules/language/language.install b/core/modules/language/language.install index 2884d4b..9e5d982 100644 --- a/core/modules/language/language.install +++ b/core/modules/language/language.install @@ -110,6 +110,7 @@ function language_enable() { // Update the language count, if the module was disabled before, the // language_count variable was forced to 1. language_update_count(); + config_install_default_config('module', 'language'); } /** diff --git a/core/modules/language/language.module b/core/modules/language/language.module index f90ef93..e7d3e2b 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -596,3 +596,15 @@ function language_url_outbound_alter(&$path, &$options, $original_path) { } } } + +/** + * Returns default language mappings. + * @todo: How can this be overridden? + */ +function language_get_mappings() { + $config = config('language.mappings'); + if ($config->isNew()) { + return FALSE; + } + return $config->get(); +} \ No newline at end of file diff --git a/core/modules/language/language.negotiation.inc b/core/modules/language/language.negotiation.inc index 0ff02d8..a363217 100644 --- a/core/modules/language/language.negotiation.inc +++ b/core/modules/language/language.negotiation.inc @@ -81,23 +81,18 @@ function language_from_browser($languages) { // Samples: "hu, en-us;q=0.66, en;q=0.33", "hu,en-us;q=0.5" $browser_langcodes = array(); if (preg_match_all('@(?<=[, ]|^)([a-zA-Z-]+|\*)(?:;q=([0-9.]+))?(?:$|\s*,\s*)@', trim($_SERVER['HTTP_ACCEPT_LANGUAGE']), $matches, PREG_SET_ORDER)) { + // Load custom mappings to support browsers that are sending non standard + // language codes. + $mappings = language_get_mappings(); foreach ($matches as $match) { - // Handle Chinese so it maps right, some browsers are sending - // wrong langcodes. - switch (strtolower($match[1])) { - case 'zh-tw': // Taiwan. - case 'zh-hk': // Hong Kong. - case 'zh-mo': // Macau. - case 'zh-cht': // Traditional Chinese. - $match[1] = 'zh-hant'; - break; - case 'zh-cn': // China. - case 'zh-sg': // Singapore. - case 'zh-chs': // Simplified Chinese. - $match[1] = 'zh-hans'; - break; + if ($mappings) { + $langcode = strtolower($match[1]); + foreach ($mappings as $browser_langcode => $drupal_langcode) { + if ($langcode == $browser_langcode) { + $match[1] = $drupal_langcode; + } + } } - // We can safely use strtolower() here, tags are ASCII. // RFC2616 mandates that the decimal part is no more than three digits, // so we multiply the qvalue by 1000 to avoid floating point comparisons. @@ -116,8 +111,16 @@ function language_from_browser($languages) { // http://blogs.msdn.com/b/ie/archive/2006/10/17/accept-language-header-for-internet-explorer-7.aspx asort($browser_langcodes); foreach ($browser_langcodes as $langcode => $qvalue) { - $generic_tag = strtok($langcode, '-'); - if (!isset($browser_langcodes[$generic_tag])) { + // For chinese languages the generic tag is either zh-hans or zh-hant, so we + // need to handle this separately. + $generic_tag = ''; + if (strlen($langcode) > 7 && (substr($langcode, 0, 7) == 'zh-hant' || substr($langcode, 0, 7) == 'zh-hans')) { + $generic_tag = substr($langcode, 0, 7); + } + else { + $generic_tag = strtok($langcode, '-'); + } + if (!empty($generic_tag) && !isset($browser_langcodes[$generic_tag])) { // Add the generic langcode, but make sure it has a lower qvalue as the // more specific one, so the more specific one gets selected if it's // defined by both the browser and Drupal. diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageBrowserDetectionUnitTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageBrowserDetectionUnitTest.php index beb18c5..b34cc93 100644 --- a/core/modules/language/lib/Drupal/language/Tests/LanguageBrowserDetectionUnitTest.php +++ b/core/modules/language/lib/Drupal/language/Tests/LanguageBrowserDetectionUnitTest.php @@ -7,13 +7,15 @@ namespace Drupal\language\Tests; -use Drupal\simpletest\UnitTestBase; +use Drupal\simpletest\WebTestBase; use Drupal\Core\Language\Language; /** * Test browser language detection. */ -class LanguageBrowserDetectionUnitTest extends UnitTestBase { +class LanguageBrowserDetectionUnitTest extends WebTestBase { + + public static $modules = array('language'); public static function getInfo() { return array( @@ -27,9 +29,6 @@ class LanguageBrowserDetectionUnitTest extends UnitTestBase { * Unit tests for the language_from_browser() function. */ function testLanguageFromBrowser() { - // Load the required functions. - require_once DRUPAL_ROOT . '/core/modules/language/language.negotiation.inc'; - $languages = array( // In our test case, 'en' has priority over 'en-US'. 'en' => new Language(array( @@ -65,6 +64,9 @@ class LanguageBrowserDetectionUnitTest extends UnitTestBase { 'zh-hant' => new Language(array( 'langcode' => 'zh-hant', )), + 'zh-hant-tw' => new Language(array( + 'langcode' => 'zh-hant', + )), ); $test_cases = array(