From e4bae8bca407fdb2c2961fa055ef8a6e867c4aaa Mon Sep 17 00:00:00 2001 From: Liangent Date: Sat, 12 May 2012 23:52:52 +0800 Subject: [PATCH] Check headers for default variant when initializing default user options. Currently, if a user with Accept-Language: zh-tw header accesses a zh site, the page contents are served in zh-tw variant, but the interface language is zh (falling back to zh-hans) so the user is seeing interface messages in zh(-hans) unless a &variant= is manually set (originally variant set in URL is checked by getDefaultVariant). There were debates that serving different languages based on headers from the same URL breaks cache, but currently contents are served in different variants based on headers and it works. So I assume this is not an issue. PS2-4: HTTP header settings shouldn't affect user preference settings of logged-in users. PS5-6: Move code loading variant settings for anonymous requests from User::getDefaultOptions() to User::loadOptions() to avoid pollution of defaults. A visual bug of this is that if I have variant set to zh and load index.php?title=Special:Preferences&variant=zh-cn, the dropdown is shown as zh-cn because I was using the default value and now it thinks the default value is zh-cn instead of zh. PS7-8: Rebase to add dependency and tweak commit summary etc. PS9: Remove the argument added to getDefaultVariant, which was intended to keep B/C of getDefaultVariant (not to check headers by default). Change-Id: Ie600ab24294a1add804875e921c32febe6ed645f --- includes/User.php | 23 +++++++++++++++++++---- languages/LanguageConverter.php | 6 +++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/includes/User.php b/includes/User.php index 93a6835d3a..e3d22b0dd5 100644 --- a/includes/User.php +++ b/includes/User.php @@ -1224,9 +1224,8 @@ class User { $defOpt = $wgDefaultUserOptions; # default language setting - $variant = $wgContLang->getDefaultVariant(); - $defOpt['variant'] = $variant; - $defOpt['language'] = $variant; + $defOpt['variant'] = $wgContLang->getCode(); + $defOpt['language'] = $wgContLang->getCode(); foreach( SearchEngine::searchableNamespaces() as $nsnum => $nsname ) { $defOpt['searchNs'.$nsnum] = !empty( $wgNamespacesToBeSearchedDefault[$nsnum] ); } @@ -4079,12 +4078,28 @@ class User { * @todo document */ protected function loadOptions() { + global $wgContLang; + $this->load(); - if ( $this->mOptionsLoaded || !$this->getId() ) + + if ( $this->mOptionsLoaded ) { return; + } $this->mOptions = self::getDefaultOptions(); + if ( !$this->getId() ) { + // For unlogged-in users, load language/variant options from request. + // There's no need to do it for logged-in users: they can set preferences, + // and handling of page content is done by $pageLang->getPreferredVariant() and such, + // so don't override user's choice (especially when the user chooses site default). + $variant = $wgContLang->getDefaultVariant(); + $this->mOptions['variant'] = $variant; + $this->mOptions['language'] = $variant; + $this->mOptionsLoaded = true; + return; + } + // Maybe load from the object if ( !is_null( $this->mOptionOverrides ) ) { wfDebug( "User: loading options for user " . $this->getId() . " from override cache.\n" ); diff --git a/languages/LanguageConverter.php b/languages/LanguageConverter.php index 8a69799e39..82e6359f1d 100644 --- a/languages/LanguageConverter.php +++ b/languages/LanguageConverter.php @@ -184,7 +184,7 @@ class LanguageConverter { /** * Get default variant. - * This function would not be affected by user's settings or headers + * This function would not be affected by user's settings * @return String: the default variant code */ public function getDefaultVariant() { @@ -192,6 +192,10 @@ class LanguageConverter { $req = $this->getURLVariant(); + if ( !$req ) { + $req = $this->getHeaderVariant(); + } + if ( $wgDefaultLanguageVariant && !$req ) { $req = $this->validateVariant( $wgDefaultLanguageVariant ); } -- 2.20.1