* Adding a new message 'exifdata', and translating it as 'Metadata'.
[lhc/web/wiklou.git] / languages / Language.php
index cdcfc89..956a049 100644 (file)
@@ -76,6 +76,7 @@ if(isset($wgExtraNamespaces)) {
        'showtoolbar'           => 1,
        'date'                  => 0,
        'imagesize'             => 2,
+       'thumbsize'             => 2,
        'rememberpassword'      => 0,
        'enotifwatchlistpages'  => 1,
        'enotifusertalkpages'   => 1,
@@ -84,8 +85,9 @@ if(isset($wgExtraNamespaces)) {
        'shownumberswatching'   => 1,
        'rcusemodstyle'         => 1,
        'showupdated'           => 1,
-       'fancysig' => 0,
-       'externaleditor' => 0,
+       'fancysig'              => 0,
+       'externaleditor'        => 0,
+       'externaldiff'          => 0,
 );
 
 /* private */ $wgQuickbarSettingsEn = array(
@@ -123,8 +125,6 @@ $wgValidationTypesEn = array (
 );
 
 # Whether to use user or default setting in Language::date()
-define( 'MW_DATE_DEFAULT', false );
-define( 'MW_DATE_USER_FORMAT', true );
 
 /* private */ $wgDateFormatsEn = array(
        'Default',
@@ -161,7 +161,8 @@ define( 'MW_DATE_USER_FORMAT', true );
        'rcusemodstyle',
        'showupdated',
        'fancysig',
-       'externaleditor'
+       'externaleditor',
+       'externaldiff',
 );
 
 /* private */ $wgBookstoreListEn = array(
@@ -267,9 +268,9 @@ global $wgRightsText;
 'tog-highlightbroken' => 'Format broken links <a href="" class="new">like this</a> (alternative: like this<a href="" class="internal">?</a>).',
 'tog-justify'  => 'Justify paragraphs',
 'tog-hideminor' => 'Hide minor edits in recent changes',
-'tog-usenewrc' => 'Enhanced recent changes (not for all browsers)',
+'tog-usenewrc' => 'Enhanced recent changes (JavaScript)',
 'tog-numberheadings' => 'Auto-number headings',
-'tog-showtoolbar'              => 'Show edit toolbar',
+'tog-showtoolbar'              => 'Show edit toolbar (JavaScript)',
 'tog-editondblclick' => 'Edit pages on double click (JavaScript)',
 'tog-editsection'              => 'Enable section editing via [edit] links',
 'tog-editsectiononrightclick'  => 'Enable section editing by right clicking<br /> on section titles (JavaScript)',
@@ -290,6 +291,7 @@ global $wgRightsText;
 'tog-showupdated'              => 'Show update marker ',
 'tog-fancysig' => 'Raw signatures (without automatic link)',
 'tog-externaleditor' => 'Use external editor by default',
+'tog-externaldiff' => 'Use external diff by default',
 
 # dates
 'sunday' => 'Sunday',
@@ -443,7 +445,6 @@ See $1.",
 "bureaucrattext"       => "The action you have requested can only be
 performed by sysops with  \"bureaucrat\" status.",
 'nbytes'               => '$1 bytes',
-'go'                   => 'Go',
 'ok'                   => 'OK',
 'sitetitle'            => "{{SITENAME}}",
 'pagetitle'            => "$1 - {{SITENAME}}",
@@ -545,6 +546,7 @@ a number of reasons why this may be so, please see
 
 You can view and copy the source of this page:",
 'seriousxhtmlerrors' => 'There were serious xhtml markup errors detected by tidy.',
+'sqlhidden' => '(SQL query hidden)',
 
 # Login and logout pages
 #
@@ -578,21 +580,17 @@ Your account has been created. Don't forget to change your {{SITENAME}} preferen
 'createaccountmail'    => 'by email',
 'badretype'            => 'The passwords you entered do not match.',
 'userexists'   => 'The user name you entered is already in use. Please choose a different name.',
-'youremail'            => 'Your email**',
-'yourrealname'         => 'Your real name*',
+'youremail'            => 'Your email²',
+'yourrealname'         => 'Your real name¹',
 'yourlanguage' => 'Interface language',
 'yourvariant'  => 'Language variant',
 'yournick'             => 'Your nickname (for signatures)',
 'emailforlost'         => "Fields marked with stars (*, **) are optional.  Storing an email address enables people to contact you through the website without you having to reveal your
 email address to them, and it can be used to send you a new password if you forget it.<br /><br />Your real name, if you choose to provide it, will be used for giving you attribution for your work.",
-'prefs-help-email'     => '** <strong>Email</strong> (optional): Enables others to contact you through your user or user_talk page without the need of revealing your
-email address. It also allows the wiki to sent you a temporary password in case you forgot your current one.',
 'prefs-help-email-enotif' => 'This address is also used to send you email notifications if you enabled the options.',
-'prefs-help-realname'  => '* <strong>Real name</strong> (optional): if you choose to provide it this will be used for giving you attribution for your work.',
-'prefs-help-userdata' => '* <strong>Real name</strong> (optional): if you choose to provide it this will be used for giving you attribution for your work.<br />
-* <strong>Email</strong> (optional): Enables people to contact you through the website without you having to reveal your
-email address to them, and it can be used to send you a new password if you forget it.',
+'prefs-help-realname'  => '¹ Real name (optional): if you choose to provide it this will be used for giving you attribution for your work.',
 'loginerror'   => 'Login error',
+'prefs-help-email'      => '² Email (optional): Enables others to contact you through your user or user_talk page without the need of revealing your',
 'nocookiesnew' => "The user account was created, but you are not logged in. {{SITENAME}} uses cookies to log in users. You have cookies disabled. Please enable them, then log in with your new username and password.",
 'nocookieslogin'       => "{{SITENAME}} uses cookies to log in users. You have cookies disabled. Please enable them and try again.",
 'noname'               => 'You have not specified a valid user name.',
@@ -847,18 +845,18 @@ $2 List redirects &nbsp; Search for $3 $9",
 #
 'preferences'  => 'Preferences',
 'prefsnologin' => 'Not logged in',
-'prefsnologintext'     => "You must be <a href=\"{{localurl:Special:Userlogin}}\">logged in</a>
+'prefsnologintext'     => "You must be [[Special:Userlogin|logged in]]
 to set user preferences.",
 'prefslogintext' => "You are logged in as \"$1\".
 Your internal ID number is $2.
 
 See [[Project:User preferences help]] for help deciphering the options.",
 'prefsreset'   => 'Preferences have been reset from storage.',
-'qbsettings'   => 'Quickbar settings',
+'qbsettings'   => 'Quickbar',
 'changepassword' => 'Change password',
 'skin'                 => 'Skin',
-'math'                 => 'Math rendering',
-'dateformat'   => 'Date format',
+'math'                 => 'Math',
+'dateformat'           => 'Date format',
 'math_failure'         => 'Failed to parse',
 'math_unknown_error'   => 'unknown error',
 'math_unknown_function'        => 'unknown function ',
@@ -869,8 +867,8 @@ See [[Project:User preferences help]] for help deciphering the options.",
 'math_bad_output'      => 'Can\'t write to or create math output directory',
 'math_notexvc' => 'Missing texvc executable; please see math/README to configure.',
 'prefs-personal' => 'User data',
-'prefs-rc' => 'Recent changes and stub display',
-'prefs-misc' => 'Misc settings',
+'prefs-rc' => 'Recent changes & stubs',
+'prefs-misc' => 'Misc',
 'saveprefs'            => 'Save preferences',
 'resetprefs'   => 'Reset preferences',
 'oldpassword'  => 'Old password',
@@ -879,7 +877,7 @@ See [[Project:User preferences help]] for help deciphering the options.",
 'textboxsize'  => 'Editing',
 'rows'                 => 'Rows',
 'columns'              => 'Columns',
-'searchresultshead' => 'Search results',
+'searchresultshead' => 'Search',
 'resultsperpage' => 'Hits to show per page',
 'contextlines' => 'Lines to show per hit',
 'contextchars' => 'Characters of context per line',
@@ -896,6 +894,7 @@ from server time (UTC).',
 'emailflag'            => 'Disable e-mail from other users',
 'defaultns'            => 'Search in these namespaces by default:',
 'default'              => 'default',
+'files'                        => 'Files',
 
 # User levels special page
 #
@@ -961,8 +960,9 @@ Unselected groups will not be changed. You can deselect a group with CTRL + Left
 'reupload'             => 'Re-upload',
 'reuploaddesc' => 'Return to the upload form.',
 'uploadnologin' => 'Not logged in',
-'uploadnologintext'    => "You must be <a href=\"{{localurl:Special:Userlogin}}\">logged in</a>
+'uploadnologintext'    => "You must be [[Special:Userlogin|logged in]]
 to upload files.",
+'upload_directory_read_only' => 'The upload directory ($1) is not writable by the webserver.',
 'uploadfile'   => 'Upload images, sounds, documents etc.',
 'uploaderror'  => 'Upload error',
 'uploadtext'   =>
@@ -1028,6 +1028,8 @@ created and by whom, and anything else you may know about it. If this is an imag
 'uploadedimage' => "uploaded \"[[$1]]\"",
 'uploaddisabled' => 'Sorry, uploading is disabled.',
 'uploadcorrupt' => 'The file is corrupt or has an incorrect extension. Please check the file and upload again.',
+'sourcefilename' => 'Source filename',
+'destfilename' => 'Destination filename',
 
 # Image list
 #
@@ -1055,6 +1057,14 @@ this old version, (rev) = revert to this old version.
 'nolinkstoimage' => 'There are no pages that link to this image.',
 'sharedupload' => 'This file is a shared upload and may be used by other projects.',
 'shareduploadwiki' => 'Please see the [$1 image description page] for further information.',
+'noimage'       => "No image by this name exists.
+
+<div class=\"editExternally\">
+'''[$1 Upload this image]'''
+</div><br clear=all />",
+'uploadnewversion' => "<div class=\"editExternally\">
+[$1 Upload a new version of this image]
+</div><br clear=all />",
 
 # Statistics
 #
@@ -1193,8 +1203,8 @@ You can narrow down the view by selecting a log type, the user name, or the affe
 # E this user
 #
 'mailnologin'  => 'No send address',
-'mailnologintext' => "You must be <a href=\"{{localurl:Special:Userlogin\">logged in</a>
-and have a valid e-mail address in your <a href=\"{{localurl:Special:Preferences}}\">preferences</a>
+'mailnologintext' => "You must be [[Special:Userlogin|logged in]]
+and have a valid e-mail address in your [[Special:Preferences|preferences]]
 to send e-mail to other users.",
 'emailuser'            => 'E-mail this user',
 'emailpage'            => 'E-mail user',
@@ -1222,7 +1232,7 @@ or has chosen not to receive e-mail from other users.',
 'watchlistsub'         => "(for user \"$1\")",
 'nowatchlist'          => 'You have no items on your watchlist.',
 'watchnologin'         => 'Not logged in',
-'watchnologintext'     => "You must be <a href=\"{{localurl:Special:Userlogin}}\">logged in</a>
+'watchnologintext'     => "You must be [[Special:Userlogin|logged in]]
 to modify your watchlist.",
 'addedwatch'           => 'Added to watchlist',
 'addedwatchtext'       => "The page \"$1\" has been added to your [[Special:Watchlist|watchlist]].
@@ -1263,7 +1273,7 @@ at the bottom of the screen (deleting a content page also deletes the accompanyi
 'updatedmarker'                => '<span class=\'updatedmarker\'>&nbsp;updated (since my last visit)&nbsp;</span>',
 
 'email_notification_mailer'            => '{{SITENAME}} Notification Mailer',
-'email_notification_infotext'          => "'''Email notification is on.'''
+'email_notification_infotext'          => "Email notification is on.
 You will be notified by email when someone changes a page which is listed in your watchlist.",
 'email_notification_reset'                     => 'Reset all notification flags (set their status to "visited")',
 'email_notification_newpagetext'=> 'This is a new page.',
@@ -1379,6 +1389,10 @@ See [[Special:Log/delete]] for a record of recent deletions and restorations.",
                 <td align="right">Namespace:</td>
                 <td align="left">$1 $2</td>
         </tr>
+       <tr>
+               <td align="right">$3</td>
+               <td>Invert</td>
+       </tr>
 </table>',
 'nocontribs'    => 'No changes were found matching these criteria.',
 'ucnote'        => "Below are this user's last <b>$1</b> changes in the last <b>$2</b> days.",
@@ -1570,7 +1584,7 @@ proceeding.',
 In those cases, you will have to move or merge the page manually if desired.',
 'movearticle'  => 'Move page',
 'movenologin'  => 'Not logged in',
-'movenologintext' => "You must be a registered user and <a href=\"{{localurl:Special:Userlogin}}\">logged in</a>
+'movenologintext' => "You must be a registered user and [[Special:Userlogin|logged in]]
 to move a page.",
 'newtitle'             => 'To new title',
 'movepagebtn'  => 'Move page',
@@ -1777,6 +1791,7 @@ ta[\'ca-nstab-category\'] = new Array(\'c\',\'View the category page\');
 'nextdiff' => 'Next diff →',
 
 'imagemaxsize' => 'Limit images on image description pages to: ',
+'thumbsize'    => 'Thumbnail size : ',
 'showbigimage' => 'Download high resolution version ($1x$2, $3 KB)',
 
 'newimages' => 'New images gallery',
@@ -1834,6 +1849,9 @@ ta[\'ca-nstab-category\'] = new Array(\'c\',\'View the category page\');
 
 'passwordtooshort' => 'Your password is too short. It must have at least $1 characters.',
 
+# Exif data
+'exifdata' => 'Metadata',
+
 # external editor support
 'edit-externally' => 'Edit this file using an external application',
 'edit-externally-help' => 'See the [http://meta.wikimedia.org/wiki/Help:External_editors setup instructions] for more information.',
@@ -1846,15 +1864,31 @@ ta[\'ca-nstab-category\'] = new Array(\'c\',\'View the category page\');
 'contributionsall' => 'all',
 );
 
+/* a fake language converter */
+class fakeConverter {
+       var $mLang;   
+       function fakeConverter($langobj) {$this->mLang = $langobj;}
+       function convert($t, $i) {return $t;}
+       function getVariants() { return array( strtolower( substr( get_class( $this->mLang ), 8 ) ) ); }
+       function getPreferredVariant() {return strtolower( substr( get_class( $this->mLang ), 8 ) );}
+       function findVariantLink(&$l, &$n) {}
+       function getExtraHashOptions() {return '';}
+       function getParsedTitle() {return '';}
+       function markNoConversion($text) {return $text;}
+}
+
 #--------------------------------------------------------------------------
 # Internationalisation code
 #--------------------------------------------------------------------------
 
 class Language {
+       var $mConverter;
        function Language() {
+
                # Copies any missing values in the specified arrays from En to the current language
                $fillin = array( 'wgSysopSpecialPages', 'wgValidSpecialPages', 'wgDeveloperSpecialPages' );
                $name = get_class( $this );
+
                if( strpos( $name, 'language' ) == 0){
                        $lang = ucfirst( substr( $name, 8 ) );
                        foreach( $fillin as $arrname ){
@@ -1868,6 +1902,7 @@ class Language {
                                }
                        }
                }
+               $this->mConverter = new fakeConverter($this);
        }
        
        /**
@@ -1891,6 +1926,9 @@ class Language {
                return $wgBookstoreListEn ;
        }
        
+       /**
+        * @return array
+        */
        function getNamespaces() {
                global $wgNamespaceNamesEn;
                return $wgNamespaceNamesEn;
@@ -2055,7 +2093,32 @@ class Language {
                  (int)substr( $ts, 0, 4 ) ); #Year
                return date( 'YmdHis', $t );
        }
+       
+       /**
+        * This is meant to be used by time(), date(), and timeanddate() to get
+        * the date preference they're supposed to use, it should be used in
+        * all children.
+        *
+        *<code>
+        * function timeanddate([...], $format = '0') {
+        *      $datePreference = $this->dateFormat($format);
+        * [...]
+        *</code>
+        *
+        * @param mixed $format
+        * @return string
+        */
+       function dateFormat( $format ) {
+               global $wgUser;
 
+               if ( !$wgUser->isLoggedIn() || $format === false ) {
+                       $options = $this->getDefaultUserOptions();
+                       return $options['date'];
+               } else {
+                       return $wgUser->getOption( 'date' );
+               }
+       }
+       
        /**
         * @access public
         * @param mixed  $ts the time format which needs to be turned into a
@@ -2068,28 +2131,18 @@ class Language {
         *               validateTimeZone() in Special:Preferences
         * @return string
         */
-       function date( $ts, $adj = false, $format = MW_DATE_USER_FORMAT, $timecorrection = false ) {
+       function date( $ts, $adj = false, $format = false, $timecorrection = false ) {
                global $wgAmericanDates, $wgUser;
                
-               $ts=wfTimestamp(TS_MW,$ts); // FIXME: Is this even needed anymore?
-
                if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
                
-               // It's probably best to turn this whole mess into a function -ævar
-               if ( $format ) {
-                       $datePreference = $wgUser->getOption( 'date' );
-               } else {
-                       $options = $this->getDefaultUserOptions();
-                       $datePreference = $options['date'];
-               }
-
-               if ($datePreference == '0') { // Not == 0 for the obvious reasons
-                       $datePreference = $wgAmericanDates ? 1 : 2;
-               }
+               $datePreference = $this->dateFormat($format);
+               
+               if ($datePreference == '0') {$datePreference = $wgAmericanDates ? '0' : '2';}
 
                $month = $this->getMonthName( substr( $ts, 4, 2 ) );
                $day = $this->formatNum( 0 + substr( $ts, 6, 2 ) );
-               $year = $this->formatNum( substr( $ts, 0, 4 ) );
+               $year = $this->formatNum( substr( $ts, 0, 4 ), true );
                
                switch( $datePreference ) {
                        case '2': return "$day $month $year";
@@ -2111,22 +2164,17 @@ class Language {
        *               validateTimeZone() in Special:Preferences
        * @return string
        */
-       function time( $ts, $adj = false, $format = MW_DATE_USER_FORMAT, $timecorrection = false ) {
+       function time( $ts, $adj = false, $format = false, $timecorrection = false ) {
                global $wgUser, $wgAmericanDates;
-               $ts=wfTimestamp(TS_MW,$ts);
 
                if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
-
-               if ( $format ) {
-                       $datePreference = $wgUser->getOption( 'date' );
-               } else {
-                       $options = $this->getDefaultUserOptions();
-                       $datePreference = $options['date'];
-               } if ($datePreference == '0') {$datePreference = $wgAmericanDates ? 1 : 2;}
+               $datePreference = $this->dateFormat($format);
+               
+               if ($datePreference == '0') {$datePreference = $wgAmericanDates ? '0' : '2';}
 
                $t = substr( $ts, 8, 2 ) . ':' . substr( $ts, 10, 2 );
                
-               if ( $format == 'ISO 8601' ) {
+               if ( $datePreference === 'ISO 8601' ) {
                        $t .= ':' . substr( $ts, 12, 2 );
                }
                return $this->formatNum( $t );
@@ -2142,32 +2190,21 @@ class Language {
        *               default one.
        * @param string $timecorrection the time offset as returned by
        *               validateTimeZone() in Special:Preferences
-       * @param ???    $dateandtime ??? (default false)
        * @return string
        */
-       function timeanddate( $ts, $adj = false, $format = MW_DATE_USER_FORMAT, $timecorrection = false, $dateandtime = false) {
+       function timeanddate( $ts, $adj = false, $format = false, $timecorrection = false) {
                global $wgUser, $wgAmericanDates;
-               $ts=wfTimestamp(TS_MW,$ts);
-
-               if ( $format ) {
-                       $datePreference = $wgUser->getOption( 'date' );
-               } else {
-                       $options = $this->getDefaultUserOptions();
-                       $datePreference = $options['date'];
-               } if ($datePreference == '0') {$datePreference = $wgAmericanDates ? 1 : 2;}
+               
+               $datePreference = $this->dateFormat($format);
                
                switch ( $datePreference ) {
-                       case 'ISO 8601': return $this->date( $ts, $adj, $format, $timecorrection ) . ' ' .
-                               $this->time( $ts, $adj, $format, $timecorrection );
-                       default: return $this->time( $ts, $adj, $format, $timecorrection ) . ', ' .
-                               $this->date( $ts, $adj, $format, $timecorrection );
+                       case 'ISO 8601': return $this->date( $ts, $adj, $datePreference, $timecorrection ) . ' ' .
+                               $this->time( $ts, $adj, $datePreference, $timecorrection );
+                       default: return $this->time( $ts, $adj, $datePreference, $timecorrection ) . ', ' .
+                               $this->date( $ts, $adj, $datePreference, $timecorrection );
                }
        }
 
-       function rfc1123( $ts ) {
-               return date( 'D, d M Y H:i:s T', $ts );
-       }
-
        function getValidSpecialPages() {
                global $wgValidSpecialPagesEn;
                return $wgValidSpecialPagesEn;
@@ -2369,11 +2406,29 @@ class Language {
         * @access public
         * @param mixed $number the string to be formatted, should be an integer or
         *        a floating point number. 
+        * @param bool $year are we being passed a year? (turns off commafication)
+        * @return mixed whatever we're fed if it's a year, a string otherwise.
+        */
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : $this->commafy($number);
+       }
+       
+       /**
+        * Adds commas to a given number
+        *
+        * @param mixed $_
+        * @return string
         */
-       function formatNum( $number ) {
-               return $number;
+       function commafy($_) {
+               return strrev((string)preg_replace('/(\d{3})(?=\d)(?!\d*\.)/','$1,',strrev($_)));
        }
 
+       /**
+        * For the credit list in includes/Credits.php (action=credits)
+        *
+        * @param array $l
+        * @return string
+        */
        function listToText( $l ) {
                $s = '';
                $m = count($l) - 1;
@@ -2412,64 +2467,106 @@ class Language {
                }
        }
 
-       # Grammatical transformations, needed for inflected languages
-       # Invoked by putting {{grammar:case|word}} in a message
+       /**
+        * Grammatical transformations, needed for inflected languages
+        * Invoked by putting {{grammar:case|word}} in a message
+        *
+        * @param string $word
+        * @param string $case
+        * @return string
+        */
        function convertGrammar( $word, $case ) {
                return $word;
        }
 
-       # languages like Chinese need to be segmented in order for the diff
-       # to be of any use
+       /**
+        * languages like Chinese need to be segmented in order for the diff
+        * to be of any use
+        *
+        * @param string $text
+        * @return string
+        */
        function segmentForDiff( $text ) {
                return $text;
        }
-       # and unsegment to show the result
+       
+       /**
+        * and unsegment to show the result
+        *
+        * @param string $text
+        * @return string
+        */
        function unsegmentForDiff( $text ) {
                return $text;
        }
 
        # convert text to different variants of a language.
        function convert( $text , $isTitle=false) {
-               return $text;
+               return $this->mConverter->convert($text, $isTitle);
        }
 
-       # returns a list of language variants for conversion.
-       # right now mainly used in the Chinese conversion
+       /**
+        * get the list of variants supported by this langauge
+        * see sample implementation in LanguageZh.php
+        *
+        * @return array an array of language codes
+        */
        function getVariants() {
-               $lang = strtolower( substr( get_class( $this ), 8 ) );
-               return array( $lang );
-       }
-       
-       # in case some variant is not defined in the markup, we need
-       # to have some fallback. for example, in zh, normally people
-       # will define zh-cn and zh-tw, but less so for zh-sg or zh-hk.
-       # when zh-sg is preferred but not defined, we will pick zh-cn
-       # in this case. right now this is only used by zh.
-       function getVariantFallback( $v ) {
-               return false;
+               return $this->mConverter->getVariants();
        }
 
+
        function getPreferredVariant() {
-               return strtolower( substr( get_class( $this ), 8 ) );
+               return $this->mConverter->getPreferredVariant();
        }
 
-       /* if a language supports multiple variants, it is
-               possible that non-existing link in one variant
-               actually exists in another variant. this function 
-               tries to find it. See e.g. LanguageZh.php
-
-       */
+       /**
+        * if a language supports multiple variants, it is
+        * possible that non-existing link in one variant
+        * actually exists in another variant. this function 
+        * tries to find it. See e.g. LanguageZh.php
+        *
+        * @param string $link the name of the link
+        * @param mixed $nt the title object of the link
+        * @return null the input parameters may be modified upon return
+        */
        function findVariantLink( &$link, &$nt ) {
-               return;
+               $this->mConverter->findVariantLink($link, $nt);
        }
 
-       /*
-               returns an array of extra options used by User::getPageRenderHash()
-       */
+       /**
+        * returns language specific options used by User::getPageRenderHash()
+        * for example, the preferred language variant
+        *
+        * @return string
+        * @access public
+        */
        function getExtraHashOptions() {
-               return '';
+               return $this->mConverter->getExtraHashOptions();
+       }
+
+       /**
+        * for languages that support multiple variants, the title of an
+        * article may be displayed differently in different variants. this
+        * function returns the apporiate title defined in the body of the article.
+        * 
+        * @return string
+        */
+       function getParsedTitle() {
+               return $this->mConverter->getParsedTitle();
        }
        
+       /**
+        * Enclose a string with the "no conversion" tag. This is used by
+        * various functions in the Parser
+        * 
+        * @param string $text text to be tagged for no conversion
+        * @return string the tagged text
+       */
+       function markNoConversion( $text ) {
+               return $this->mConverter->markNoConversion( $text );
+       }
+
        /**
         * A regular expression to match legal word-trailing characters
         * which should be merged onto a link of the form [[foo]]bar.
@@ -2487,6 +2584,7 @@ class Language {
                return $this;
        }
 
+
 }
 
 # This should fail gracefully if there's not a localization available