r20721 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r20720‎ | r20721 | r20722 >
Date:23:23, 26 March 2007
Author:daniel
Status:old (Comments)
Tags:
Comment:
new extension allowing localized interface for anonymous visitors
Modified paths:
  • /trunk/extensions/LanguageSelector (added) (history)
  • /trunk/extensions/LanguageSelector/LanguageSelector.php (added) (history)
  • /trunk/extensions/LanguageSelector/README (added) (history)
  • /trunk/extensions/LanguageSelector/install.settings (added) (history)

Diff [purge]

Index: trunk/extensions/LanguageSelector/install.settings
@@ -0,0 +1,2 @@
 2+require_once( "{{path}}/LanguageSelector.php" );
 3+
Index: trunk/extensions/LanguageSelector/LanguageSelector.php
@@ -0,0 +1,351 @@
 2+<?php
 3+/**
 4+ * LanguageSelector extension - language selector on every page, also for visitors
 5+ *
 6+ * Features:
 7+ * * Automatic detection of the language to use for anonymous visitors
 8+ * * Ads selector for preferred language to every page (also works for anons)
 9+ *
 10+ * This can be combined with Polyglot and MultiLang to provide more internationalization support.
 11+ *
 12+ *
 13+ * @package MediaWiki
 14+ * @subpackage Extensions
 15+ * @author Daniel Kinzler, brightbyte.de
 16+ * @copyright © 2007 Daniel Kinzler
 17+ * @licence GNU General Public Licence 2.0 or later
 18+ */
 19+
 20+if( !defined( 'MEDIAWIKI' ) ) {
 21+ echo( "This file is an extension to the MediaWiki software and cannot be used standalone.\n" );
 22+ die( 1 );
 23+}
 24+
 25+$wgExtensionCredits['other'][] = array(
 26+ 'name' => 'LanguageSelector',
 27+ 'author' => 'Daniel Kinzler',
 28+ 'url' => 'http://mediawiki.org/wiki/Extension:LanguageSelector',
 29+ 'description' => 'language selector on every page, also for visitors',
 30+);
 31+
 32+define( 'LANGUAGE_SELECTOR_USE_CONTENT_LANG', 0 ); #no detection
 33+define( 'LANGUAGE_SELECTOR_PREFER_CONTENT_LANG', 1 ); #use content language if accepted by the client
 34+define( 'LANGUAGE_SELECTOR_PREFER_CLIENT_LANG', 2 ); #use language most preferred by the client
 35+
 36+/**
 37+* Language detection mode for anonymous visitors.
 38+* Possible values:
 39+* * LANGUAGE_SELECTOR_USE_CONTENT_LANG - use the $wgLanguageCode setting (default content language)
 40+* * LANGUAGE_SELECTOR_PREFER_CONTENT_LANG - use the $wgLanguageCode setting, if accepted by the client
 41+* * LANGUAGE_SELECTOR_USE_CONTENT_LANG - use the client's preferred language, if in $wgLanguageSelectorLanguages
 42+*/
 43+$wgLanguageSelectorDetectLanguage = LANGUAGE_SELECTOR_PREFER_CLIENT_LANG;
 44+
 45+/**
 46+* Languages to offer in the language selector. Per default, this includes all languages MediaWiki knows
 47+* about by virtue of $wgLanguageNames. A shorter list may be more usable, though.
 48+* If the Polyglot extension is installed, $wgPolyglotLanguages is used as fallback.
 49+*/
 50+$wgLanguageSelectorLanguages = NULL;
 51+
 52+define( 'LANGUAGE_SELECTOR_MANUAL', 0 ); #don't place anywhere
 53+define( 'LANGUAGE_SELECTOR_AT_TOP_OF_TEXT', 1 ); #put at the top of page content
 54+define( 'LANGUAGE_SELECTOR_IN_TOOLBOX', 2 ); #put into toolbox
 55+define( 'LANGUAGE_SELECTOR_AS_PORTLET', 3 ); #as portlet
 56+define( 'LANGUAGE_SELECTOR_INTO_SITENOTICE', 11); #put after sitenotice text
 57+define( 'LANGUAGE_SELECTOR_INTO_TITLE', 12); #put after title text
 58+define( 'LANGUAGE_SELECTOR_INTO_SUBTITLE', 13); #put after subtitle text
 59+define( 'LANGUAGE_SELECTOR_INTO_CATLINKS', 14); #put after catlinks text
 60+
 61+$wgLanguageSelectorLocation = LANGUAGE_SELECTOR_AT_TOP_OF_TEXT;
 62+
 63+///// hook it up /////////////////////////////////////////////////////
 64+$wgHooks['AbortNewAccount'][] = 'wfLanguageSelectorAbortNewAccount'; //abuse hook to inject default language option //FIXME: doesn't quite work it seems :(
 65+
 66+$wgExtensionFunctions[] = "wfLanguageSelectorExtension";
 67+
 68+$wgLanguageSelectorRequestedLanguage = NULL;
 69+
 70+function wfLanguageSelectorExtension() {
 71+ global $wgLanguageSelectorLanguages, $wgLanguageSelectorDetectLanguage, $wgLanguageSelectorRequestedLanguage, $wgLanguageSelectorLocation;
 72+ global $wgUser, $wgLang, $wgRequest, $wgCookiePrefix, $wgCookiePath, $wgMessageCache, $wgOut, $wgJsMimeType, $wgHooks, $wgParser;
 73+
 74+ $wgParser->setHook('languageselector', 'wfLanguageSelectorTag' );
 75+
 76+ $wgMessageCache->addMessage('languageselector-setlang', 'set');
 77+
 78+ if ( $wgLanguageSelectorLanguages === NULL ) {
 79+ $wgLanguageSelectorLanguages = @$GLOBALS['wgPolyglotLanguages'];
 80+ }
 81+
 82+ if ( $wgLanguageSelectorLanguages === NULL ) {
 83+ $wgLanguageSelectorLanguages = array_keys( $GLOBALS['wgLanguageNames'] );
 84+ }
 85+
 86+ $setlang = $wgRequest->getVal('setlang');
 87+ if ($setlang && !in_array($setlang, $wgLanguageSelectorLanguages)) $setlang = NULL; //ignore invalid
 88+
 89+ if ($setlang) {
 90+ setcookie($wgCookiePrefix.'LanguageSelectorLanguage', $setlang, 0, $wgCookiePath);
 91+ $wgLanguageSelectorRequestedLanguage = $setlang;
 92+ }
 93+ else {
 94+ $wgLanguageSelectorRequestedLanguage = @$_COOKIE[$wgCookiePrefix.'LanguageSelectorLanguage'];
 95+ }
 96+
 97+ if ( !$wgUser->isAnon() && $setlang ) {
 98+ if ($setlang != $wgUser->getOption('language')) {
 99+ $wgUser->setOption('language', $wgLanguageSelectorRequestedLanguage);
 100+ $wgUser->saveSettings();
 101+ }
 102+ }
 103+
 104+ if ( $wgUser->isAnon() && !$wgRequest->getVal( 'uselang' )) {
 105+
 106+ //NOTE: we need this for anons, so squids don't get confused.
 107+ // but something is still wrong with caching...
 108+ header('Vary: Cookie', false); //hrm, this is pretty BAD.
 109+ header('Vary: Accept-Language', false);
 110+
 111+ if ( $wgLanguageSelectorRequestedLanguage || $wgLanguageSelectorDetectLanguage != LANGUAGE_SELECTOR_USE_CONTENT_LANG ) {
 112+
 113+ if (!class_exists('StubAutoLang')) {
 114+ class StubAutoLang extends StubObject {
 115+ function __construct() {
 116+ parent::__construct( 'wgLang' );
 117+ }
 118+
 119+ function __call( $name, $args ) {
 120+ return $this->_call( $name, $args );
 121+ }
 122+
 123+ //partially copied from StubObject.php. There should be a better way...
 124+ function _newObject() {
 125+ global $wgContLanguageCode, $wgContLang, $wgLanguageSelectorDetectLanguage, $wgLanguageSelectorRequestedLanguage;
 126+
 127+ $code = $wgLanguageSelectorRequestedLanguage;
 128+ if (!$code) $code = wfLanguageSelectorDetectLanguage($wgLanguageSelectorDetectLanguage);
 129+
 130+ if( $code == $wgContLanguageCode ) {
 131+ return $wgContLang;
 132+ } else {
 133+ $obj = Language::factory( $code );
 134+ return $obj;
 135+ }
 136+ }
 137+ }
 138+ }
 139+
 140+ $wgLang = new StubAutoLang;
 141+ }
 142+ }
 143+
 144+ if ($wgLanguageSelectorLocation != LANGUAGE_SELECTOR_MANUAL) {
 145+ switch($wgLanguageSelectorLocation) {
 146+ case LANGUAGE_SELECTOR_AT_TOP_OF_TEXT: $wgHooks['BeforePageDisplay'][] = 'wfLanguageSelectorBeforePageDisplay'; break;
 147+ case LANGUAGE_SELECTOR_IN_TOOLBOX: $wgHooks['MonoBookTemplateToolboxEnd'][] = 'wfLanguageSelectorSkinHook'; break;
 148+ default:
 149+ $wgHooks['SkinTemplateOutputPageBeforeExec'][] = 'wfLanguageSelectorSkinTemplateOutputPageBeforeExec'; break;
 150+ }
 151+ }
 152+
 153+ $wgOut->addScript('<script type="'.$wgJsMimeType.'">
 154+ addOnloadHook(function() {
 155+ var i = 1;
 156+ while ( true ) {
 157+ var btn = document.getElementById("languageselector-commit-"+i);
 158+ var sel = document.getElementById("languageselector-select-"+i);
 159+ var idx = i;
 160+
 161+ if (!btn) break;
 162+
 163+ btn.style.display = "none";
 164+ sel.onchange = function() { this.parentNode.submit(); };
 165+
 166+ i++;
 167+ }
 168+ });
 169+ </script>');
 170+}
 171+
 172+function wfLanguageSelectorBeforePageDisplay( &$out ) {
 173+ $html = wfLanguageSelectorHTML();
 174+ $out->mBodytext = $html . $out->mBodytext;
 175+ return true;
 176+}
 177+
 178+function wfLanguageSelectorSkinHook( &$out ) {
 179+ $html = wfLanguageSelectorHTML();
 180+ print $html;
 181+ return true;
 182+}
 183+
 184+function wfLanguageSelectorTag($input, $args) {
 185+ $style = @$args['style'];
 186+ $class = @$args['class'];
 187+ $selectorstyle = @$args['selectorstyle'];
 188+ $buttonstyle = @$args['buttonstyle'];
 189+
 190+ if ($style) $style = htmlspecialchars($style);
 191+ if ($class) $class = htmlspecialchars($class);
 192+ if ($selectorstyle) $selectorstyle = htmlspecialchars($selectorstyle);
 193+ if ($buttonstyle) $buttonstyle = htmlspecialchars($buttonstyle);
 194+
 195+ return wfLanguageSelectorHTML( $style, $class, $selectorstyle, $buttonstyle );
 196+}
 197+
 198+function wfLanguageSelectorSkinTemplateOutputPageBeforeExec( &$skin, &$tpl ) {
 199+ global $wgLanguageSelectorLocation, $wgLanguageSelectorLanguages;
 200+ global $wgLang, $wgContLang, $wgTitle;
 201+
 202+ if ($wgLanguageSelectorLocation == LANGUAGE_SELECTOR_AS_PORTLET) {
 203+ $code = $wgLang->getCode();
 204+ $lines = array();
 205+ foreach ($wgLanguageSelectorLanguages as $ln) {
 206+ $lines[] = array(
 207+ $href = $wgTitle->getFullURL( 'setlang=' . $ln ),
 208+ 'text' => $wgContLang->getLanguageName($ln),
 209+ 'href' => $href,
 210+ 'id' => 'n-languageselector',
 211+ 'active' => ($ln == $code),
 212+ );
 213+ }
 214+
 215+ $tpl->data['sidebar']['languageselector'] = $lines;
 216+ return;
 217+ }
 218+
 219+ $key = NULL;
 220+
 221+ switch($wgLanguageSelectorLocation) {
 222+ case LANGUAGE_SELECTOR_INTO_SITENOTICE: $key = 'sitenotice'; break;
 223+ case LANGUAGE_SELECTOR_INTO_TITLE: $key = 'title'; break;
 224+ case LANGUAGE_SELECTOR_INTO_SUBTITLE: $key = 'subtitle'; break;
 225+ case LANGUAGE_SELECTOR_INTO_CATLINKS: $key = 'catlinks'; break;
 226+ }
 227+
 228+ if ($key) {
 229+ $html = wfLanguageSelectorHTML();
 230+ $tpl->set( $key, $tpl->data[ $key ] . $html );
 231+ }
 232+
 233+ return true;
 234+}
 235+
 236+function wfLanguageSelectorDetectLanguage($mode) {
 237+ global $wgContLang, $wgLanguageSelectorLanguages;
 238+
 239+ $contLang = $wgContLang->getCode();
 240+
 241+ if (!$mode || $mode == LANGUAGE_SELECTOR_USE_CONTENT_LANG) {
 242+ return $contLang;
 243+ }
 244+
 245+ /**
 246+ * get accepted languages from Accept-Languages
 247+ * HTTP header.
 248+ */
 249+ $l= @$_SERVER["HTTP_ACCEPT_LANGUAGE"];
 250+
 251+ if (empty($l)) return $contLang;
 252+
 253+ $l= split(',',$l);
 254+
 255+ /**
 256+ * normalize accepted languages
 257+ */
 258+ $languages= array();
 259+ foreach ($l as $lan) {
 260+ $lan= trim($lan);
 261+
 262+ $idx= strpos($lan,';');
 263+ if ($idx !== false) {
 264+ #FIXME: qualifiers are ignored, order is relevant!
 265+ $lan= substr($lan,0,$idx);
 266+ $lan= trim($lan);
 267+ }
 268+
 269+ $languages[]= $lan;
 270+
 271+ $idx= strpos($lan,'-');
 272+ if ($idx !== false) {
 273+ $lan= substr($lan,0,$idx);
 274+ $languages[]= $lan;
 275+ }
 276+ }
 277+
 278+ /**
 279+ * see if the content language is accepted by the
 280+ * client.
 281+ */
 282+ if ( ($mode == LANGUAGE_SELECTOR_PREFER_CONTENT_LANG)
 283+ && in_array($contLang,$languages) ) {
 284+ return $contLang;
 285+ }
 286+
 287+ /**
 288+ * look for a language that is acceptable to the client
 289+ * and known to the wiki.
 290+ */
 291+ foreach($wgLanguageSelectorLanguages as $code) {
 292+ /**
 293+ * TODO: only accept languages for which an implementation exists.
 294+ * this is disabled, because it's slow. Note that this code is
 295+ * executed for every page request!
 296+ */
 297+ /*
 298+ global $IP;
 299+ $langfile="$IP/languages/Language".str_replace('-', '_', ucfirst($code)).".php";
 300+ if(!file_exists($langfile)) {
 301+ continue;
 302+ }
 303+ */
 304+
 305+ if (in_array($code,$languages)) {
 306+ return $code;
 307+ }
 308+ }
 309+
 310+ return $contLang;
 311+}
 312+
 313+function wfLanguageSelectorAbortNewAccount( &$u ) { //FIXME: doesn't quite work it seems :(
 314+ global $wgUser;
 315+
 316+ //inherit language;
 317+ //if $wgUser->isAnon, this means remembering what the user selected
 318+ //otherwise, it would mean inheriting the language from the user creating the account.
 319+ if ($wgUser->isAnon()) {
 320+ $u->setOption('language', $wgUser->getOption('language'));
 321+ }
 322+
 323+ return true;
 324+}
 325+
 326+function wfLanguageSelectorHTML( $style = NULL, $class = NULL, $selectorstyle = NULL, $buttonstyle = NULL ) {
 327+ global $wgLanguageSelectorLanguages, $wgTitle, $wgLang, $wgContLang;
 328+
 329+ static $id = 0;
 330+ $id += 1;
 331+
 332+ $code = $wgLang->getCode();
 333+ $url = $wgTitle->getFullURL();
 334+
 335+ $html = '';
 336+ $html .= Xml::openElement('span', array('id' => 'languageselector-box-'.$id, 'class' => 'languageselector ' . $class, 'style' => $style ));
 337+ $html .= Xml::openElement('form', array('name' => 'languageselector-form-'.$id, 'id' => 'languageselector-form-'.$id, 'method' => 'get', 'action' => $url, 'style' => 'display:inline;'));
 338+ $html .= Xml::openElement('select', array('name' => 'setlang', 'id' => 'languageselector-select-'.$id, 'style' => $selectorstyle));
 339+
 340+ foreach ($wgLanguageSelectorLanguages as $ln) {
 341+ $html .= Xml::option($wgContLang->getLanguageName($ln), $ln, $ln == $code);
 342+ }
 343+
 344+ $html .= Xml::closeElement('select');
 345+ $html .= Xml::submitButton(wfMsg('languageselector-setlang'), array( 'id' => 'languageselector-commit-'.$id, 'style' => $buttonstyle ));
 346+ $html .= Xml::closeElement('form');
 347+ $html .= Xml::closeElement('span');
 348+
 349+ return $html;
 350+}
 351+
 352+?>
\ No newline at end of file
Index: trunk/extensions/LanguageSelector/README
@@ -0,0 +1,93 @@
 2+--------------------------------------------------------------------------
 3+README for the LanguageSelector extension
 4+Copyright © 2007 Daniel Kinzler
 5+Licenses: GNU General Public License (GPL)
 6+ GNU Free Documentation License (GFDL)
 7+--------------------------------------------------------------------------
 8+
 9+LanguageSelector is EXPERIMENTAL
 10+
 11+The LanguageSelector extension provides detection of the language to use for
 12+anonymous visitors, and a menu for selecting the user language on each page,
 13+for logged in users as well as anonymous visitors. It also provides an
 14+additional tag, <languageselector>, for embedding the selector into wiki
 15+pages and system messages.
 16+
 17+Language detection is based on the Accept-Language header sent by the
 18+browser as part of the HTTP request. Users can also set their preferred
 19+language explicitly - this is handled by a separate cookie for anonymous
 20+visitors, and in the user preferences for logged in users.
 21+
 22+NOTE: language detection and cookie-based language preferences for anonymous
 23+users will currently not work with page caching (MediaWiki filecache, reverse
 24+HTTP proxies like squid, etc). It may degrade cache performance and make it
 25+useless, and it may lead to people seeing the page in a random language.
 26+Mediawiki's internal caches (parser, link, query, etc) are not effectd.
 27+
 28+For more comprehensive support for multilingual content, LanguageSelector can
 29+be combined with the MultiLang and Polyglot extensions.
 30+
 31+The LanguageSelector extension was originally written by Daniel Kinzler in 2007
 32+and is released under the GNU General Public License (GPL).
 33+
 34+<http://mediawiki.org/wiki/Extension:LanguageSelector>
 35+
 36+== Installing ==
 37+
 38+Copy the LanguageSelector directory into the extensions folder of your
 39+MediaWiki installation. Then add the following line to your
 40+LocalSettings.php file (near the end):
 41+
 42+ require_once( "$IP/extensions/LanguageSelector/LanguageSelector.php" );
 43+
 44+== Configuration ==
 45+
 46+You can specify the following settings in your LocalSettings.php (after
 47+including the extension file):
 48+
 49+* $wgLanguageSelectorLanguages: Languages to be offered to the user for
 50+ selection. If set to NULL (the default), all languages known to MediaWiki
 51+ (by $wgLanguageNames) are considered. If the Polyglot extension is
 52+ installed and $wgPolyglotLanguages is set, that value will be used as a
 53+ fallback. Setting $wgLanguageSelectorLanguages to a shorter list may
 54+ be more convenient for users than selecting from a list with more than a
 55+ hundred mostly useless entries.
 56+
 57+* $wgLanguageSelectorDetectLanguage: Language detection mode for anonymous
 58+ visitors. Possible values:
 59+** LANGUAGE_SELECTOR_USE_CONTENT_LANG: do not use detection, always use the
 60+ wiki's content language (this is mediawiki's normal behavior).
 61+** LANGUAGE_SELECTOR_PREFER_CONTENT_LANG: use the wiki's content language,
 62+ setting, if accepted by the client.
 63+** LANGUAGE_SELECTOR_PREFER_CLIENT_LANG: use the client's preferred
 64+ language, if it is in $wgLanguageSelectorLanguages.
 65+
 66+* $wgLanguageSelectorLocation: where to inject the language selector
 67+ widget. Note that you will probably have to adjust your CSS styles
 68+ to adopt the language selector to your wiki's style.
 69+ Possible values of $wgLanguageSelectorLocation:
 70+** LANGUAGE_SELECTOR_MANUAL: do not show language selector. This can be
 71+ usefull if you only want to use the auto-detection feature, or only want
 72+ the selector on a few pages, or if you want to place it manually by
 73+ putting it into an appropriate system message.
 74+** LANGUAGE_SELECTOR_AT_TOP_OF_TEXT: inject a dropdown box at the top of page
 75+ content. This is the default, but it looks quite ugly without extra CSS
 76+ rules applied.
 77+** LANGUAGE_SELECTOR_IN_TOOLBOX: inject a dropdown box at the bottom of the
 78+ toolbox in the sidebar. This only works with the MonoBook skin, or skins
 79+ explicitly supporting the MonoBookTemplateToolboxEnd hook.
 80+** LANGUAGE_SELECTOR_AS_PORTLET: inject the language selector as a portlet
 81+ in the sidebar, similar to how interlanguage-links are shown.
 82+ Works with MonoBook skin, may also work with some SkinTemplate-based skins.
 83+** LANGUAGE_SELECTOR_INTO_SITENOTICE: inject a dropdown box at the end of
 84+ the sitenotice text. Ugly without additional CSS rules applied.
 85+ Works with MonoBook skin, may also work with some SkinTemplate-based skins.
 86+** LANGUAGE_SELECTOR_INTO_TITLE: inject a dropdown box at the end of
 87+ the page title. Ugly without additional CSS rules applied.
 88+ Works with MonoBook skin, may also work with some SkinTemplate-based skins.
 89+** LANGUAGE_SELECTOR_INTO_SUBTITLE: inject a dropdown box at the end of
 90+ the subtitle. Ugly without additional CSS rules applied.
 91+ Works with MonoBook skin, may also work with some SkinTemplate-based skins.
 92+** LANGUAGE_SELECTOR_INTO_CATLINKS: inject a dropdown box at the end of
 93+ the category box. Ugly without additional CSS rules applied.
 94+ Works with MonoBook skin, may also work with some SkinTemplate-based skins.

Comments

#Comment by Jeremyb (talk | contribs)   21:34, 7 June 2012

LanguageSelector/LanguageSelector.php line 8.

s/ Ads / Adds / ?