Commit 2eb25ee7 authored by Dries's avatar Dries

- Patch #956256 by plach: () is only set if language is detected from the URL.

parent f97d94ea
......@@ -22,6 +22,12 @@
*/
define('LOCALE_LANGUAGE_NEGOTIATION_INTERFACE', 'locale-interface');
/**
* If no URL language is available language is determined using an already
* detected one.
*/
define('LOCALE_LANGUAGE_NEGOTIATION_URL_FALLBACK', 'locale-url-fallback');
/**
* The language is set based on the user language settings.
*/
......@@ -210,6 +216,53 @@ function locale_language_from_url($languages) {
return $language_url;
}
/**
* Determines the language to be assigned to URLs when none is detected.
*
* The language negotiation process has a fallback chain that ends with the
* default language provider. Each built-in language type has a separate
* initialization:
* - Interface language, which is the only configurable one, always gets a valid
* value. If no request-specific language is detected, the default language
* will be used.
* - Content language merely inherits the interface language by default.
* - URL language is detected from the requested URL and will be used to rewrite
* URLs appearing in the page being rendered. If no language can be detected,
* there are two possibilities:
* - If the default language has no configured path prefix or domain, then the
* default language is used. This guarantees that (missing) URL prefixes are
* preserved when navigating through the site.
* - If the default language has a configured path prefix or domain, a
* requested URL having an empty prefix or domain is an anomaly that must be
* fixed. This is done by introducing a prefix or domain in the rendered
* page matching the detected interface language.
*
* @param $languages
* (optional) An array of valid language objects. This is passed by
* language_provider_invoke() to every language provider callback, but it is
* not actually needed here. Defaults to NULL.
* @param $language_type
* (optional) The language type to fall back to. Defaults to the interface
* language.
*
* @return
* A valid language code.
*/
function locale_language_url_fallback($language = NULL, $language_type = LANGUAGE_TYPE_INTERFACE) {
$default = language_default();
$prefix = (variable_get('locale_language_negotiation_url_part', LOCALE_LANGUAGE_NEGOTIATION_URL_PREFIX) == LOCALE_LANGUAGE_NEGOTIATION_URL_PREFIX);
// If the default language is not configured to convey language information,
// a missing URL language information indicates that URL language should be
// the default one, otherwise we fall back to an already detected language.
if (($prefix && empty($default->prefix)) || (!$prefix && empty($default->domain))) {
return $default->language;
}
else {
return $GLOBALS[$language_type]->language;
}
}
/**
* Return the URL language switcher block. Translation links may be provided by
* other modules.
......
......@@ -112,6 +112,17 @@ function locale_update_7001() {
return array();
}
/**
* Updates URL language negotiation by adding the URL fallback detection method.
*/
function locale_update_7002() {
$language_types_info = language_types_info();
$info = $language_types_info[LANGUAGE_TYPE_URL];
if (isset($info['fixed'])) {
language_negotiation_set(LANGUAGE_TYPE_URL, array_flip($info['fixed']));
}
}
/**
* @} End of "defgroup updates-6.x-to-7.x"
*/
......
......@@ -503,8 +503,8 @@ function locale_entity_info_alter(&$entity_info) {
* language negotiated value. It is used by the Field API to determine the
* display language for fields if no explicit value is specified.
* - URL language is by default non-configurable and is determined through the
* URL language provider. It is used by l() as the default language if none is
* specified.
* URL language provider or the URL fallback provider if no language can be
* detected. It is used by l() as the default language if none is specified.
*/
function locale_language_types_info() {
require_once DRUPAL_ROOT . '/includes/locale.inc';
......@@ -517,7 +517,7 @@ function locale_language_types_info() {
'fixed' => array(LOCALE_LANGUAGE_NEGOTIATION_INTERFACE),
),
LANGUAGE_TYPE_URL => array(
'fixed' => array(LOCALE_LANGUAGE_NEGOTIATION_URL),
'fixed' => array(LOCALE_LANGUAGE_NEGOTIATION_URL, LOCALE_LANGUAGE_NEGOTIATION_URL_FALLBACK),
),
);
}
......@@ -582,6 +582,15 @@ function locale_language_negotiation_info() {
'description' => t('Use the detected interface language.'),
);
$providers[LOCALE_LANGUAGE_NEGOTIATION_URL_FALLBACK] = array(
'types' => array(LANGUAGE_TYPE_URL),
'callbacks' => array('language' => 'locale_language_url_fallback'),
'file' => $file,
'weight' => 8,
'name' => t('URL fallback'),
'description' => t('Use an already detected language for URLs if none is found.'),
);
return $providers;
}
......
......@@ -1730,15 +1730,14 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase {
parent::setUp('locale', 'locale_test');
require_once DRUPAL_ROOT . '/includes/language.inc';
drupal_load('module', 'locale');
$admin_user = $this->drupalCreateUser(array('administer languages', 'translate interface', 'access administration pages', 'administer blocks'));
$this->drupalLogin($admin_user);
}
/**
* 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';
......@@ -1892,6 +1891,50 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase {
$this->drupalGet($test['path'], array(), $test['http_header']);
$this->assertText($test['expect'], $test['message']);
}
/**
* Test URL language detection when the requested URL has no language.
*/
function testUrlLanguageFallback() {
// Add the Italian language.
$language_browser_fallback = 'it';
locale_add_language($language_browser_fallback);
$languages = language_list();
// Enable the path prefix for the default language: this way any unprefixed
// URL must have a valid fallback value.
$edit = array('prefix' => 'en');
$this->drupalPost('admin/config/regional/language/edit/en', $edit, t('Save language'));
// Enable browser and URL language detection.
$edit = array(
'language[enabled][locale-browser]' => TRUE,
'language[enabled][locale-url]' => TRUE,
'language[weight][locale-browser]' => -8,
'language[weight][locale-url]' => -10,
);
$this->drupalPost('admin/config/regional/language/configure', $edit, t('Save settings'));
$this->drupalGet('admin/config/regional/language/configure');
// Enable the language switcher block.
$edit = array('blocks[locale_language][region]' => 'sidebar_first');
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
// Access the front page without specifying any valid URL language prefix
// and having as browser language preference a non-default language.
$http_header = array("Accept-Language: $language_browser_fallback;q=1");
$this->drupalGet('', array(), $http_header);
// Check that the language switcher active link matches the given browser
// language.
$args = array(':url' => base_path() . (!empty($GLOBALS['conf']['clean_url']) ? $language_browser_fallback : "?q=$language_browser_fallback"));
$fields = $this->xpath('//div[@id="block-locale-language"]//a[@class="language-link active" and @href=:url]', $args);
$this->assertTrue($fields[0] == $languages[$language_browser_fallback]->native, t('The browser language is the URL active language'));
// Check that URLs are rewritten using the given browser language.
$fields = $this->xpath('//div[@id="site-name"]//a[@rel="home" and @href=:url]//span', $args);
$this->assertTrue($fields[0] == 'Drupal', t('URLs are rewritten using the browser language.'));
}
}
/**
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment