Check headers for default variant when initializing default user options.
authorLiangent <liangent@gmail.com>
Sat, 12 May 2012 15:52:52 +0000 (23:52 +0800)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 10 Oct 2012 04:31:59 +0000 (04:31 +0000)
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
languages/LanguageConverter.php

index 93a6835..e3d22b0 100644 (file)
@@ -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" );
index 8a69799..82e6359 100644 (file)
@@ -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 );
                }