diff --git a/modules/locale/locale.test b/modules/locale/locale.test index 03c4bcf337729a6c4fdd5cf231ffc37721b69f2c..47f52cd4935ddccf85ca3d14b1fa16e078bb3e4d 100644 --- a/modules/locale/locale.test +++ b/modules/locale/locale.test @@ -1408,3 +1408,195 @@ class LocaleContentFunctionalTest extends DrupalWebTestCase { } } + + +/** + * Test UI language negotiation + * 1. LANGUAGE_NEGOTIATION_PATH_DEFAULT + * UI Language base on URL prefix, browser language preference has no + * influence: + * admin/config + * UI in site default language + * zh-hans/admin/config + * UI in Chinese + * blah-blah/admin/config + * 404 + * 2. LANGUAGE_NEGOTIATION_PATH + * admin/config + * UI in user's browser language preference if the site has that + * language enabled, if not, the default language + * zh-hans/admin/config + * UI in Chinese + * blah-blah/admin/config + * 404 + * 3. LANGUAGE_NEGOTIATION_DOMAIN + * http://example.com/admin/config + * UI language in site default + * http://example.cn/admin/config + * UI language in Chinese + */ +class UILanguageNegotiationTest extends DrupalWebTestCase { + public static function getInfo() { + return array( + 'name' => 'UI language negotiation', + 'description' => 'Test UI language switching by url path prefix and domain.', + 'group' => 'Locale', + ); + } + + function setUp() { + parent::setUp('locale', 'locale_test'); + } + + /** + * Tests for language switching by URL path. + */ + function testUILanguageNegotiation() { + $admin_user = $this->drupalCreateUser(array('administer languages', 'translate interface', 'access administration pages')); + $this->drupalLogin($admin_user); + + // A few languages to switch to. + // This one is unknown, should get the default lang version. + $language_unknown = 'blah-blah'; + // For testing browser lang preference. + $language_browser_fallback = 'vi'; + // For testing path prefix. + $language = 'zh-hans'; + // For setting browser language preference to 'vi'. + $http_header_browser_fallback = array("Accept-Language: $language_browser_fallback;q=1"); + // For setting browser language preference to some unknown. + $http_header_blah = array("Accept-Language: blah;q=1"); + + // This domain should switch the UI to Chinese. + $language_domain = 'example.cn'; + + // Setup the site languages by installing two languages. + require_once('includes/locale.inc'); + locale_add_language($language_browser_fallback); + locale_add_language($language); + + // We will look for this string in the admin/config screen to see if the + // corresponding translated string is shown. + $default_string = 'Configure languages for content and the user interface'; + + // Set the default language in order for the translated string to be registered + // into database when seen by t(). Without doing this, our target string + // is for some reason not found when doing translate search. This might + // be some bug. + $languages = language_list('enabled'); + variable_set('language_default', $languages[1]['vi']); + // First visit this page to make sure our target string is searchable. + $this->drupalGet('admin/config'); + // Now the t()'ed string is in db so switch the language back to default. + variable_del('language_default'); + + // Translate the string. + $language_browser_fallback_string = "In $language_browser_fallback In $language_browser_fallback In $language_browser_fallback"; + $language_string = "In $language In $language In $language"; + // Do a translate search of our target string. + $edit = array( 'string' => $default_string); + $this->drupalPost('admin/config/international/translate/translate', $edit, t('Filter')); + // Should find the string and now click edit to post translated string. + $this->clickLink('edit'); + $edit = array( + "translations[$language_browser_fallback]" => $language_browser_fallback_string, + "translations[$language]" => $language_string, + ); + $this->drupalPost(NULL, $edit, t('Save translations')); + + $tests = array( + // Default, browser preference should have no influence. + array( + 'language_negotiation' => LANGUAGE_NEGOTIATION_PATH_DEFAULT, + 'path' => 'admin/config', + 'expect' => $default_string, + 'http_header' => $http_header_browser_fallback, + 'message' => 'LANGUAGE_NEGOTIATION_PATH_DEFAULT: no language prefix, UI language is default and not the browser language preference setting is used.', + ), + // Language prefix. + array( + 'language_negotiation' => LANGUAGE_NEGOTIATION_PATH_DEFAULT, + 'path' => "$language/admin/config", + 'expect' => $language_string, + 'http_header' => $http_header_browser_fallback, + 'message' => 'LANGUAGE_NEGOTIATION_PATH_DEFAULT: with language prefix, UI language is switched based on path prefix', + ), + // Default, go by browser preference. + array( + 'language_negotiation' => LANGUAGE_NEGOTIATION_PATH, + 'path' => 'admin/config', + 'expect' => $language_browser_fallback_string, + 'http_header' => $http_header_browser_fallback, + 'message' => 'LANGUAGE_NEGOTIATION_PATH: no language prefix, UI language is determined by browser language preference', + ), + // Prefix, switch to the language. + array( + 'language_negotiation' => LANGUAGE_NEGOTIATION_PATH, + 'path' => "$language/admin/config", + 'expect' => $language_string, + 'http_header' => $http_header_browser_fallback, + 'message' => 'LANGUAGE_NEGOTIATION_PATH: with langage prefix, UI language is based on path prefix', + ), + // Default, browser language preference is not one of site's lang. + array( + 'language_negotiation' => LANGUAGE_NEGOTIATION_PATH, + 'path' => 'admin/config', + 'expect' => $default_string, + 'http_header' => $http_header_blah, + 'message' => 'LANGUAGE_NEGOTIATION_PATH: no language prefix and browser language preference set to unknown language should use default language', + ), + ); + + foreach ($tests as $test) { + $this->runTest($test); + } + + // Unknown language prefix should return 404. + foreach(array(LANGUAGE_NEGOTIATION_PATH_DEFAULT, LANGUAGE_NEGOTIATION_PATH) as $negotiation) { + variable_set('language_negotiation', $negotiation); + $this->drupalGet("$language_unknown/admin/config", array(), $http_header_browser_fallback); + $this->assertResponse(404, "Unknown language path prefix should return 404, code = $negotiation"); + } + + // Setup for domain negotiation, first configure the language to have domain + // URL. + $edit = array('prefix' => '', 'domain' => "http://$language_domain"); + $this->drupalPost("admin/config/international/language/edit/$language", $edit, t('Save language')); + // Set the site to use domain language negotiation. + variable_set('language_negotiation', LANGUAGE_NEGOTIATION_DOMAIN); + + $tests = array( + // Default domain, browser preference should have no influence. + array( + 'path' => 'admin/config', + 'expect' => $default_string, + 'http_header' => $http_header_browser_fallback, + 'message' => 'LANGUAGE_NEGOTIATION_DOMAIN: default domain should get default language', + ), + // Language domain specific URL, we set the $_SERVER['HTTP_HOST'] in + // locale_test.module hook_boot() to simulate this. + array( + 'locale_test_domain' => $language_domain, + 'path' => 'admin/config', + 'expect' => $language_string, + 'http_header' => $http_header_browser_fallback, + 'message' => 'LANGUAGE_NEGOTIATION_DOMAIN: domain example.cn should switch to Chinese', + ), + ); + + foreach ($tests as $test) { + $this->runTest($test); + } + } + + private function runTest($test) { + if (!empty($test['language_negotiation'])) { + variable_set('language_negotiation', $test['language_negotiation']); + } + if (!empty($test['locale_test_domain'])) { + variable_set('locale_test_domain', $test['locale_test_domain']); + } + $this->drupalGet($test['path'], array(), $test['http_header']); + $this->assertText($test['expect'], $test['message']); + } +} diff --git a/modules/locale/tests/locale_test.module b/modules/locale/tests/locale_test.module index 87423f04b822ee577fd7562ee98527bce70ec37a..ca0524ab95aaf959714a6404f8164ee933890435 100644 --- a/modules/locale/tests/locale_test.module +++ b/modules/locale/tests/locale_test.module @@ -15,3 +15,13 @@ function locale_test_locale($op = 'groups') { return array('custom' => t('Custom')); } } + +/** + * For testing domain language negotiation, we fake it by setting + * the HTTP_HOST here + */ +function locale_test_boot() { + if (variable_get('locale_test_domain')) { + $_SERVER['HTTP_HOST'] = variable_get('locale_test_domain'); + } +}