Index: trunk/phase3/includes/User.php |
— | — | @@ -1024,7 +1024,7 @@ |
1025 | 1025 | /** |
1026 | 1026 | * default language setting |
1027 | 1027 | */ |
1028 | | - $variant = $wgContLang->getPreferredVariant( false ); |
| 1028 | + $variant = $wgContLang->getDefaultVariant(); |
1029 | 1029 | $defOpt['variant'] = $variant; |
1030 | 1030 | $defOpt['language'] = $variant; |
1031 | 1031 | foreach( SearchEngine::searchableNamespaces() as $nsnum => $nsname ) { |
Index: trunk/phase3/includes/OutputPage.php |
— | — | @@ -1430,7 +1430,17 @@ |
1431 | 1431 | if( $variant === $wgContLang->getCode() ) { |
1432 | 1432 | continue; |
1433 | 1433 | } else { |
1434 | | - $aloption[] = "string-contains=$variant"; |
| 1434 | + $aloption[] = 'string-contains=' . $variant; |
| 1435 | + |
| 1436 | + // IE and some other browsers use another form of language code |
| 1437 | + // in their Accept-Language header, like "zh-CN" or "zh-TW". |
| 1438 | + // We should handle these too. |
| 1439 | + $ievariant = explode( '-', $variant ); |
| 1440 | + if ( count( $ievariant ) == 2 ) { |
| 1441 | + $ievariant[1] = strtoupper( $ievariant[1] ); |
| 1442 | + $ievariant = implode( '-', $ievariant ); |
| 1443 | + $aloption[] = 'string-contains=' . $ievariant; |
| 1444 | + } |
1435 | 1445 | } |
1436 | 1446 | } |
1437 | 1447 | $this->addVaryHeader( 'Accept-Language', $aloption ); |
Index: trunk/phase3/includes/Wiki.php |
— | — | @@ -208,19 +208,11 @@ |
209 | 209 | throw new ErrorPageError( 'badtitle', 'badtitletext' ); |
210 | 210 | } |
211 | 211 | // Redirect loops, no title in URL, $wgUsePathInfo URLs, and URLs with a variant |
212 | | - } else if( $action == 'view' && !$request->wasPosted() && |
213 | | - ( ( !$request->getVal( 'title' ) || $title->getPrefixedDBKey() != $request->getText( 'title' ) ) || |
214 | | - // No valid variant in URL (if the main-language has multi-variants), to ensure |
215 | | - // anonymous access would always be redirect to a URL with 'variant' parameter |
216 | | - ( !$request->getVal( 'variant' ) && $wgContLang->hasVariants() && !$wgUser->isLoggedIn() ) ) && |
217 | | - !count( array_diff( array_keys( $request->getValues() ), array( 'action', 'title' ) ) ) ) |
| 212 | + } else if( $action == 'view' && !$request->wasPosted() |
| 213 | + && ( ( !$request->getVal( 'title' ) || $title->getPrefixedDBKey() != $request->getText( 'title' ) ) ) |
| 214 | + && !count( array_diff( array_keys( $request->getValues() ), array( 'action', 'title' ) ) ) ) |
218 | 215 | { |
219 | | - if( !$wgUser->isLoggedIn() ) { |
220 | | - $pref = $wgContLang->getPreferredVariant( false, $fromHeader = true ); |
221 | | - $targetUrl = $title->getFullURL( '', $variant = $pref ); |
222 | | - } |
223 | | - else |
224 | | - $targetUrl = $title->getFullURL(); |
| 216 | + $targetUrl = $title->getFullURL(); |
225 | 217 | // Redirect to canonical url, make it a 301 to allow caching |
226 | 218 | if( $targetUrl == $request->getFullRequestURL() ) { |
227 | 219 | $message = "Redirect loop detected!\n\n" . |
Index: trunk/phase3/includes/Title.php |
— | — | @@ -869,14 +869,6 @@ |
870 | 870 | $query = wfArrayToCGI( $query ); |
871 | 871 | } |
872 | 872 | |
873 | | - // internal links should point to same variant as current page (only anonymous users) |
874 | | - if ( !$variant && $wgContLang->hasVariants() && !$wgUser->isLoggedIn() ) { |
875 | | - $pref = $wgContLang->getPreferredVariant( false ); |
876 | | - if ( $pref != $wgContLang->getCode() ) { |
877 | | - $variant = $pref; |
878 | | - } |
879 | | - } |
880 | | - |
881 | 873 | if ( $this->isExternal() ) { |
882 | 874 | $url = $this->getFullURL(); |
883 | 875 | if ( $query ) { |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -1971,6 +1971,9 @@ |
1972 | 1972 | /** Whether to enable language variant conversion for links. */ |
1973 | 1973 | $wgDisableTitleConversion = false; |
1974 | 1974 | |
| 1975 | +/** Whether to enable language cononical in meta data. */ |
| 1976 | +$wgDisableLangCanonical = false; |
| 1977 | + |
1975 | 1978 | /** Default variant code, if false, the default will be the language code */ |
1976 | 1979 | $wgDefaultLanguageVariant = false; |
1977 | 1980 | |
Index: trunk/phase3/includes/Skin.php |
— | — | @@ -249,12 +249,23 @@ |
250 | 250 | } |
251 | 251 | |
252 | 252 | /** |
253 | | - * Adds metadata links (Creative Commons/Dublin Core/copyright) to the HTML |
254 | | - * output. |
| 253 | + * Adds metadata links below to the HTML output. |
| 254 | + * <ol> |
| 255 | + * <li>Creative Commons |
| 256 | + * <br />See http://wiki.creativecommons.org/Extend_Metadata. |
| 257 | + * </li> |
| 258 | + * <li>Dublin Core</li> |
| 259 | + * <li>Use hreflang to specify canonical and alternate links |
| 260 | + * <br />See http://www.google.com/support/webmasters/bin/answer.py?answer=189077 |
| 261 | + * </li> |
| 262 | + * <li>Copyright</li> |
| 263 | + * <ol> |
| 264 | + * |
255 | 265 | * @param $out Object: instance of OutputPage |
256 | 266 | */ |
257 | 267 | function addMetadataLinks( OutputPage $out ) { |
258 | 268 | global $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf; |
| 269 | + global $wgDisableLangConversion, $wgDisableLangCanonical, $wgContLang; |
259 | 270 | global $wgRightsPage, $wgRightsUrl; |
260 | 271 | |
261 | 272 | if ( $out->isArticleRelated() ) { |
— | — | @@ -275,6 +286,29 @@ |
276 | 287 | ); |
277 | 288 | } |
278 | 289 | } |
| 290 | + |
| 291 | + if ( !$wgDisableLangConversion && !$wgDisableLangCanonical |
| 292 | + && $wgContLang->hasVariants() ) { |
| 293 | + |
| 294 | + $urlvar = $wgContLang->getURLVariant(); |
| 295 | + |
| 296 | + if ( !$urlvar ) { |
| 297 | + $variants = $wgContLang->getVariants(); |
| 298 | + foreach ( $variants as $_v ) { |
| 299 | + $out->addLink( array( |
| 300 | + 'rel' => 'alternate', |
| 301 | + 'hreflang' => $_v, |
| 302 | + 'href' => $this->mTitle->getLocalURL( '', $_v ) ) |
| 303 | + ); |
| 304 | + } |
| 305 | + } else { |
| 306 | + $out->addLink( array( |
| 307 | + 'rel' => 'canonical', |
| 308 | + 'href' => $this->mTitle->getFullURL() ) |
| 309 | + ); |
| 310 | + } |
| 311 | + } |
| 312 | + |
279 | 313 | $copyright = ''; |
280 | 314 | if ( $wgRightsPage ) { |
281 | 315 | $copy = Title::newFromText( $wgRightsPage ); |
Index: trunk/phase3/languages/LanguageConverter.php |
— | — | @@ -134,20 +134,18 @@ |
135 | 135 | |
136 | 136 | /** |
137 | 137 | * Get preferred language variant. |
138 | | - * @param $fromUser Boolean: get it from $wgUser's preferences |
139 | | - * @param $fromHeader Boolean: get it from Accept-Language |
140 | 138 | * @return String: the preferred language code |
141 | 139 | */ |
142 | | - public function getPreferredVariant( $fromUser = true, $fromHeader = false ) { |
143 | | - global $wgDefaultLanguageVariant; |
| 140 | + public function getPreferredVariant() { |
| 141 | + global $wgDefaultLanguageVariant, $wgUser; |
144 | 142 | |
145 | 143 | $req = $this->getURLVariant(); |
146 | 144 | |
147 | | - if ( $fromUser && !$req ) { |
| 145 | + if ( $wgUser->isLoggedIn() && !$req ) { |
148 | 146 | $req = $this->getUserVariant(); |
149 | 147 | } |
150 | 148 | |
151 | | - if ( $fromHeader && !$req ) { |
| 149 | + elseif ( !$req ) { |
152 | 150 | $req = $this->getHeaderVariant(); |
153 | 151 | } |
154 | 152 | |
— | — | @@ -166,6 +164,26 @@ |
167 | 165 | } |
168 | 166 | |
169 | 167 | /** |
| 168 | + * Get default variant. |
| 169 | + * This function would not be affected by user's settings or headers |
| 170 | + * @return String: the default variant code |
| 171 | + */ |
| 172 | + public function getDefaultVariant() { |
| 173 | + global $wgDefaultLanguageVariant; |
| 174 | + |
| 175 | + $req = $this->getURLVariant(); |
| 176 | + |
| 177 | + if ( $wgDefaultLanguageVariant && !$req ) { |
| 178 | + $req = $this->validateVariant( $wgDefaultLanguageVariant ); |
| 179 | + } |
| 180 | + |
| 181 | + if ( $req ) { |
| 182 | + return $req; |
| 183 | + } |
| 184 | + return $this->mMainLanguageCode; |
| 185 | + } |
| 186 | + |
| 187 | + /** |
170 | 188 | * Validate the variant |
171 | 189 | * @param $variant String: the variant to validate |
172 | 190 | * @return Mixed: returns the variant if it is valid, null otherwise |
— | — | @@ -183,7 +201,7 @@ |
184 | 202 | * |
185 | 203 | * @return Mixed: variant if one found, false otherwise. |
186 | 204 | */ |
187 | | - protected function getURLVariant() { |
| 205 | + public function getURLVariant() { |
188 | 206 | global $wgRequest; |
189 | 207 | |
190 | 208 | if ( $this->mURLVariant ) { |
Index: trunk/phase3/languages/Language.php |
— | — | @@ -44,6 +44,8 @@ |
45 | 45 | function convertTitle( $t ) { return $t->getPrefixedText(); } |
46 | 46 | function getVariants() { return array( $this->mLang->getCode() ); } |
47 | 47 | function getPreferredVariant() { return $this->mLang->getCode(); } |
| 48 | + function getDefaultVariant() { return $this->mLang->getCode(); } |
| 49 | + function getURLVariant() { return ''; } |
48 | 50 | function getConvRuleTitle() { return false; } |
49 | 51 | function findVariantLink( &$l, &$n, $ignoreOtherCond = false ) { } |
50 | 52 | function getExtraHashOptions() { return ''; } |
— | — | @@ -2673,9 +2675,17 @@ |
2674 | 2676 | return $this->mConverter->getVariants(); |
2675 | 2677 | } |
2676 | 2678 | |
2677 | | - function getPreferredVariant( $fromUser = true, $fromHeader = false ) { |
2678 | | - return $this->mConverter->getPreferredVariant( $fromUser, $fromHeader ); |
| 2679 | + function getPreferredVariant() { |
| 2680 | + return $this->mConverter->getPreferredVariant(); |
2679 | 2681 | } |
| 2682 | + |
| 2683 | + function getDefaultVariant() { |
| 2684 | + return $this->mConverter->getDefaultVariant(); |
| 2685 | + } |
| 2686 | + |
| 2687 | + function getURLVariant() { |
| 2688 | + return $this->mConverter->getURLVariant(); |
| 2689 | + } |
2680 | 2690 | |
2681 | 2691 | /** |
2682 | 2692 | * If a language supports multiple variants, it is |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -186,6 +186,8 @@ |
187 | 187 | is usually to set it to -1 to disable the limit) |
188 | 188 | * (bug 25397) Allow uploading (not displaying) of WebP images, disabled by default |
189 | 189 | * (bug 23194) Special:ListFiles now has thumbnails |
| 190 | +* Use hreflang to specify canonical and alternate links, search engine friendly |
| 191 | + when a wiki has multiple variant languages. |
190 | 192 | |
191 | 193 | === Bug fixes in 1.17 === |
192 | 194 | * (bug 17560) Half-broken deletion moved image files to deletion archive |