(bug 5462) Bogus missing patch warning in updater
[mediawiki.git] / languages / Language.php
blob465de238d8e67c7d8edfb38b363a1f7f06c39342
1 <?php
2 /**
3 * @package MediaWiki
4 * @subpackage Language
5 */
7 if( defined( 'MEDIAWIKI' ) ) {
10 # In general you should not make customizations in these language files
11 # directly, but should use the MediaWiki: special namespace to customize
12 # user interface messages through the wiki.
13 # See http://meta.wikipedia.org/wiki/MediaWiki_namespace
15 # NOTE TO TRANSLATORS: Do not copy this whole file when making translations!
16 # A lot of common constants and a base class with inheritable methods are
17 # defined here, which should not be redefined. See the other LanguageXx.php
18 # files for examples.
21 #--------------------------------------------------------------------------
22 # Language-specific text
23 #--------------------------------------------------------------------------
25 if($wgMetaNamespace === FALSE)
26 $wgMetaNamespace = str_replace( ' ', '_', $wgSitename );
28 /* private */ $wgNamespaceNamesEn = array(
29 NS_MEDIA => 'Media',
30 NS_SPECIAL => 'Special',
31 NS_MAIN => '',
32 NS_TALK => 'Talk',
33 NS_USER => 'User',
34 NS_USER_TALK => 'User_talk',
35 NS_PROJECT => $wgMetaNamespace,
36 NS_PROJECT_TALK => $wgMetaNamespace . '_talk',
37 NS_IMAGE => 'Image',
38 NS_IMAGE_TALK => 'Image_talk',
39 NS_MEDIAWIKI => 'MediaWiki',
40 NS_MEDIAWIKI_TALK => 'MediaWiki_talk',
41 NS_TEMPLATE => 'Template',
42 NS_TEMPLATE_TALK => 'Template_talk',
43 NS_HELP => 'Help',
44 NS_HELP_TALK => 'Help_talk',
45 NS_CATEGORY => 'Category',
46 NS_CATEGORY_TALK => 'Category_talk',
49 if(isset($wgExtraNamespaces)) {
50 $wgNamespaceNamesEn=$wgNamespaceNamesEn+$wgExtraNamespaces;
53 /* private */ $wgDefaultUserOptionsEn = array(
54 'quickbar' => 1,
55 'underline' => 2,
56 'cols' => 80,
57 'rows' => 25,
58 'searchlimit' => 20,
59 'contextlines' => 5,
60 'contextchars' => 50,
61 'skin' => $wgDefaultSkin,
62 'math' => 1,
63 'rcdays' => 7,
64 'rclimit' => 50,
65 'highlightbroken' => 1,
66 'stubthreshold' => 0,
67 'previewontop' => 1,
68 'editsection' => 1,
69 'editsectiononrightclick'=> 0,
70 'showtoc' => 1,
71 'showtoolbar' => 1,
72 'date' => 0,
73 'imagesize' => 2,
74 'thumbsize' => 2,
75 'rememberpassword' => 0,
76 'enotifwatchlistpages' => 0,
77 'enotifusertalkpages' => 1,
78 'enotifminoredits' => 0,
79 'enotifrevealaddr' => 0,
80 'shownumberswatching' => 1,
81 'fancysig' => 0,
82 'externaleditor' => 0,
83 'externaldiff' => 0,
84 'showjumplinks' => 1,
85 'numberheadings' => 0,
86 'uselivepreview' => 0,
89 /* private */ $wgQuickbarSettingsEn = array(
90 'None', 'Fixed left', 'Fixed right', 'Floating left', 'Floating right'
93 /* private */ $wgSkinNamesEn = array(
94 'standard' => 'Classic',
95 'nostalgia' => 'Nostalgia',
96 'cologneblue' => 'Cologne Blue',
97 'davinci' => 'DaVinci',
98 'mono' => 'Mono',
99 'monobook' => 'MonoBook',
100 'myskin' => 'MySkin',
101 'chick' => 'Chick'
104 /* private */ $wgMathNamesEn = array(
105 MW_MATH_PNG => 'mw_math_png',
106 MW_MATH_SIMPLE => 'mw_math_simple',
107 MW_MATH_HTML => 'mw_math_html',
108 MW_MATH_SOURCE => 'mw_math_source',
109 MW_MATH_MODERN => 'mw_math_modern',
110 MW_MATH_MATHML => 'mw_math_mathml'
114 * Whether to use user or default setting in Language::date()
116 * NOTE: the array string values are no longer important!
117 * The actual date format functions are now called for the selection in
118 * Special:Preferences, and the 'datedefault' message for MW_DATE_DEFAULT.
120 * The array keys make up the set of formats which this language allows
121 * the user to select. It's exposed via Language::getDateFormats().
123 * @access private
125 $wgDateFormatsEn = array(
126 MW_DATE_DEFAULT => 'No preference',
127 MW_DATE_DMY => '16:12, 15 January 2001',
128 MW_DATE_MDY => '16:12, January 15, 2001',
129 MW_DATE_YMD => '16:12, 2001 January 15',
130 MW_DATE_ISO => '2001-01-15 16:12:34'
133 /* private */ $wgUserTogglesEn = array(
134 'highlightbroken',
135 'justify',
136 'hideminor',
137 'usenewrc',
138 'numberheadings',
139 'showtoolbar',
140 'editondblclick',
141 'editsection',
142 'editsectiononrightclick',
143 'showtoc',
144 'rememberpassword',
145 'editwidth',
146 'watchcreations',
147 'watchdefault',
148 'minordefault',
149 'previewontop',
150 'previewonfirst',
151 'nocache',
152 'enotifwatchlistpages',
153 'enotifusertalkpages',
154 'enotifminoredits',
155 'enotifrevealaddr',
156 'shownumberswatching',
157 'fancysig',
158 'externaleditor',
159 'externaldiff',
160 'showjumplinks',
161 'uselivepreview',
162 'autopatrol',
163 'forceeditsummary',
166 /* private */ $wgBookstoreListEn = array(
167 'AddALL' => 'http://www.addall.com/New/Partner.cgi?query=$1&type=ISBN',
168 'PriceSCAN' => 'http://www.pricescan.com/books/bookDetail.asp?isbn=$1',
169 'Barnes & Noble' => 'http://search.barnesandnoble.com/bookSearch/isbnInquiry.asp?isbn=$1',
170 'Amazon.com' => 'http://www.amazon.com/exec/obidos/ISBN=$1'
173 # Read language names
174 global $wgLanguageNames;
175 /** */
176 require_once( 'Names.php' );
178 $wgLanguageNamesEn =& $wgLanguageNames;
181 /* private */ $wgWeekdayNamesEn = array(
182 'sunday', 'monday', 'tuesday', 'wednesday', 'thursday',
183 'friday', 'saturday'
187 /* private */ $wgMonthNamesEn = array(
188 'january', 'february', 'march', 'april', 'may_long', 'june',
189 'july', 'august', 'september', 'october', 'november',
190 'december'
192 /* private */ $wgMonthNamesGenEn = array(
193 'january-gen', 'february-gen', 'march-gen', 'april-gen', 'may-gen', 'june-gen',
194 'july-gen', 'august-gen', 'september-gen', 'october-gen', 'november-gen',
195 'december-gen'
198 /* private */ $wgMonthAbbreviationsEn = array(
199 'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug',
200 'sep', 'oct', 'nov', 'dec'
203 # Note to translators:
204 # Please include the English words as synonyms. This allows people
205 # from other wikis to contribute more easily.
207 /* private */ $wgMagicWordsEn = array(
208 # ID CASE SYNONYMS
209 MAG_REDIRECT => array( 0, '#REDIRECT' ),
210 MAG_NOTOC => array( 0, '__NOTOC__' ),
211 MAG_FORCETOC => array( 0, '__FORCETOC__' ),
212 MAG_TOC => array( 0, '__TOC__' ),
213 MAG_NOEDITSECTION => array( 0, '__NOEDITSECTION__' ),
214 MAG_START => array( 0, '__START__' ),
215 MAG_CURRENTMONTH => array( 1, 'CURRENTMONTH' ),
216 MAG_CURRENTMONTHNAME => array( 1, 'CURRENTMONTHNAME' ),
217 MAG_CURRENTMONTHNAMEGEN => array( 1, 'CURRENTMONTHNAMEGEN' ),
218 MAG_CURRENTMONTHABBREV => array( 1, 'CURRENTMONTHABBREV' ),
219 MAG_CURRENTDAY => array( 1, 'CURRENTDAY' ),
220 MAG_CURRENTDAY2 => array( 1, 'CURRENTDAY2' ),
221 MAG_CURRENTDAYNAME => array( 1, 'CURRENTDAYNAME' ),
222 MAG_CURRENTYEAR => array( 1, 'CURRENTYEAR' ),
223 MAG_CURRENTTIME => array( 1, 'CURRENTTIME' ),
224 MAG_NUMBEROFARTICLES => array( 1, 'NUMBEROFARTICLES' ),
225 MAG_NUMBEROFFILES => array( 1, 'NUMBEROFFILES' ),
226 MAG_PAGENAME => array( 1, 'PAGENAME' ),
227 MAG_PAGENAMEE => array( 1, 'PAGENAMEE' ),
228 MAG_NAMESPACE => array( 1, 'NAMESPACE' ),
229 MAG_NAMESPACEE => array( 1, 'NAMESPACEE' ),
230 MAG_FULLPAGENAME => array( 1, 'FULLPAGENAME' ),
231 MAG_FULLPAGENAMEE => array( 1, 'FULLPAGENAMEE' ),
232 MAG_SUBPAGENAME => array( 0, 'SUBPAGENAME' ),
233 MAG_SUBPAGENAMEE => array( 0, 'SUBPAGENAMEE' ),
234 MAG_MSG => array( 0, 'MSG:' ),
235 MAG_SUBST => array( 0, 'SUBST:' ),
236 MAG_MSGNW => array( 0, 'MSGNW:' ),
237 MAG_END => array( 0, '__END__' ),
238 MAG_IMG_THUMBNAIL => array( 1, 'thumbnail', 'thumb' ),
239 MAG_IMG_MANUALTHUMB => array( 1, 'thumbnail=$1', 'thumb=$1'),
240 MAG_IMG_RIGHT => array( 1, 'right' ),
241 MAG_IMG_LEFT => array( 1, 'left' ),
242 MAG_IMG_NONE => array( 1, 'none' ),
243 MAG_IMG_WIDTH => array( 1, '$1px' ),
244 MAG_IMG_CENTER => array( 1, 'center', 'centre' ),
245 MAG_IMG_FRAMED => array( 1, 'framed', 'enframed', 'frame' ),
246 MAG_INT => array( 0, 'INT:' ),
247 MAG_SITENAME => array( 1, 'SITENAME' ),
248 MAG_NS => array( 0, 'NS:' ),
249 MAG_LOCALURL => array( 0, 'LOCALURL:' ),
250 MAG_LOCALURLE => array( 0, 'LOCALURLE:' ),
251 MAG_SERVER => array( 0, 'SERVER' ),
252 MAG_SERVERNAME => array( 0, 'SERVERNAME' ),
253 MAG_SCRIPTPATH => array( 0, 'SCRIPTPATH' ),
254 MAG_GRAMMAR => array( 0, 'GRAMMAR:' ),
255 MAG_NOTITLECONVERT => array( 0, '__NOTITLECONVERT__', '__NOTC__'),
256 MAG_NOCONTENTCONVERT => array( 0, '__NOCONTENTCONVERT__', '__NOCC__'),
257 MAG_CURRENTWEEK => array( 1, 'CURRENTWEEK' ),
258 MAG_CURRENTDOW => array( 1, 'CURRENTDOW' ),
259 MAG_REVISIONID => array( 1, 'REVISIONID' ),
260 MAG_PLURAL => array( 0, 'PLURAL:' ),
261 MAG_FULLURL => array( 0, 'FULLURL:' ),
262 MAG_FULLURLE => array( 0, 'FULLURLE:' ),
263 MAG_LCFIRST => array( 0, 'LCFIRST:' ),
264 MAG_UCFIRST => array( 0, 'UCFIRST:' ),
265 MAG_LC => array( 0, 'LC:' ),
266 MAG_UC => array( 0, 'UC:' ),
267 MAG_RAW => array( 0, 'RAW:' ),
270 if (!$wgCachedMessageArrays) {
271 require_once('Messages.php');
274 /* a fake language converter */
275 class fakeConverter {
276 var $mLang;
277 function fakeConverter($langobj) {$this->mLang = $langobj;}
278 function convert($t, $i) {return $t;}
279 function parserConvert($t, $p) {return $t;}
280 function getVariants() { return array( $this->mLang->getCode() ); }
281 function getPreferredVariant() {return $this->mLang->getCode(); }
282 function findVariantLink(&$l, &$n) {}
283 function getExtraHashOptions() {return '';}
284 function getParsedTitle() {return '';}
285 function markNoConversion($text) {return $text;}
286 function convertCategoryKey( $key ) {return $key; }
290 #--------------------------------------------------------------------------
291 # Internationalisation code
292 #--------------------------------------------------------------------------
294 class Language {
295 var $mConverter;
296 function Language() {
298 # Copies any missing values in the specified arrays from En to the current language
299 $fillin = array( 'wgSysopSpecialPages', 'wgValidSpecialPages', 'wgDeveloperSpecialPages' );
300 $name = get_class( $this );
302 if( strpos( $name, 'language' ) == 0){
303 $lang = ucfirst( substr( $name, 8 ) );
304 foreach( $fillin as $arrname ){
305 $langver = "{$arrname}{$lang}";
306 $enver = "{$arrname}En";
307 if( ! isset( $GLOBALS[$langver] ) || ! isset( $GLOBALS[$enver] ))
308 continue;
309 foreach($GLOBALS[$enver] as $spage => $text){
310 if( ! isset( $GLOBALS[$langver][$spage] ) )
311 $GLOBALS[$langver][$spage] = $text;
315 $this->mConverter = new fakeConverter($this);
319 * Exports the default user options as defined in
320 * $wgDefaultUserOptionsEn, user preferences can override some of these
321 * depending on what's in (Local|Default)Settings.php and some defines.
323 * @return array
325 function getDefaultUserOptions() {
326 global $wgDefaultUserOptionsEn ;
327 return $wgDefaultUserOptionsEn ;
331 * Exports $wgBookstoreListEn
332 * @return array
334 function getBookstoreList() {
335 global $wgBookstoreListEn ;
336 return $wgBookstoreListEn ;
340 * @return array
342 function getNamespaces() {
343 global $wgNamespaceNamesEn;
344 return $wgNamespaceNamesEn;
348 * A convenience function that returns the same thing as
349 * getNamespaces() except with the array values changed to ' '
350 * where it found '_', useful for producing output to be displayed
351 * e.g. in <select> forms.
353 * @return array
355 function getFormattedNamespaces() {
356 $ns = $this->getNamespaces();
357 foreach($ns as $k => $v) {
358 $ns[$k] = strtr($v, '_', ' ');
360 return $ns;
364 * Get a namespace value by key
365 * <code>
366 * $mw_ns = $wgContLang->getNsText( NS_MEDIAWIKI );
367 * echo $mw_ns; // prints 'MediaWiki'
368 * </code>
370 * @param int $index the array key of the namespace to return
371 * @return mixed, string if the namespace value exists, otherwise false
373 function getNsText( $index ) {
374 $ns = $this->getNamespaces();
375 return isset( $ns[$index] ) ? $ns[$index] : false;
379 * A convenience function that returns the same thing as
380 * getNsText() except with '_' changed to ' ', useful for
381 * producing output.
383 * @return array
385 function getFormattedNsText( $index ) {
386 $ns = $this->getNsText( $index );
387 return strtr($ns, '_', ' ');
391 * Get a namespace key by value, case insensetive.
393 * @param string $text
394 * @return mixed An integer if $text is a valid value otherwise false
396 function getNsIndex( $text ) {
397 $ns = $this->getNamespaces();
399 foreach ( $ns as $i => $n ) {
400 if ( strcasecmp( $n, $text ) == 0)
401 return $i;
403 return false;
407 * short names for language variants used for language conversion links.
409 * @param string $code
410 * @return string
412 function getVariantname( $code ) {
413 return wfMsg( "variantname-$code" );
416 function specialPage( $name ) {
417 return $this->getNsText(NS_SPECIAL) . ':' . $name;
420 function getQuickbarSettings() {
421 global $wgQuickbarSettingsEn;
422 return $wgQuickbarSettingsEn;
425 function getSkinNames() {
426 global $wgSkinNamesEn;
427 return $wgSkinNamesEn;
430 function getMathNames() {
431 global $wgMathNamesEn;
432 return $wgMathNamesEn;
435 function getDateFormats() {
436 global $wgDateFormatsEn;
437 return $wgDateFormatsEn;
440 function getUserToggles() {
441 global $wgUserTogglesEn;
442 return $wgUserTogglesEn;
445 function getUserToggle( $tog ) {
446 return wfMsg( "tog-$tog" );
449 function getLanguageNames() {
450 global $wgLanguageNamesEn;
451 return $wgLanguageNamesEn;
454 function getLanguageName( $code ) {
455 global $wgLanguageNamesEn;
456 if ( ! array_key_exists( $code, $wgLanguageNamesEn ) ) {
457 return '';
459 return $wgLanguageNamesEn[$code];
462 function getMonthName( $key ) {
463 global $wgMonthNamesEn, $wgContLang;
464 // see who called us and use the correct message function
465 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
466 return wfMsgForContent($wgMonthNamesEn[$key-1]);
467 else
468 return wfMsg($wgMonthNamesEn[$key-1]);
471 /* by default we just return base form */
472 function getMonthNameGen( $key ) {
473 return $this->getMonthName( $key );
476 function getMonthAbbreviation( $key ) {
477 global $wgMonthAbbreviationsEn, $wgContLang;
478 // see who called us and use the correct message function
479 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
480 return wfMsgForContent(@$wgMonthAbbreviationsEn[$key-1]);
481 else
482 return wfMsg(@$wgMonthAbbreviationsEn[$key-1]);
485 function getWeekdayName( $key ) {
486 global $wgWeekdayNamesEn, $wgContLang;
487 // see who called us and use the correct message function
488 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
489 return wfMsgForContent($wgWeekdayNamesEn[$key-1]);
490 else
491 return wfMsg($wgWeekdayNamesEn[$key-1]);
495 * Used by date() and time() to adjust the time output.
496 * @access public
497 * @param int $ts the time in date('YmdHis') format
498 * @param mixed $tz adjust the time by this amount (default false)
499 * @return int
502 function userAdjust( $ts, $tz = false ) {
503 global $wgUser, $wgLocalTZoffset;
505 if (!$tz) {
506 $tz = $wgUser->getOption( 'timecorrection' );
509 if ( $tz === '' ) {
510 $hrDiff = isset( $wgLocalTZoffset ) ? $wgLocalTZoffset : 0;
511 $minDiff = 0;
512 } elseif ( strpos( $tz, ':' ) !== false ) {
513 $tzArray = explode( ':', $tz );
514 $hrDiff = intval($tzArray[0]);
515 $minDiff = intval($hrDiff < 0 ? -$tzArray[1] : $tzArray[1]);
516 } else {
517 $hrDiff = intval( $tz );
519 if ( 0 == $hrDiff && 0 == $minDiff ) { return $ts; }
521 $t = mktime( (
522 (int)substr( $ts, 8, 2) ) + $hrDiff, # Hours
523 (int)substr( $ts, 10, 2 ) + $minDiff, # Minutes
524 (int)substr( $ts, 12, 2 ), # Seconds
525 (int)substr( $ts, 4, 2 ), # Month
526 (int)substr( $ts, 6, 2 ), # Day
527 (int)substr( $ts, 0, 4 ) ); #Year
528 return date( 'YmdHis', $t );
532 * This is meant to be used by time(), date(), and timeanddate() to get
533 * the date preference they're supposed to use, it should be used in
534 * all children.
536 *<code>
537 * function timeanddate([...], $format = true) {
538 * $datePreference = $this->dateFormat($format);
539 * [...]
540 *</code>
542 * @param mixed $usePrefs: if true, the user's preference is used
543 * if false, the site/language default is used
544 * if int/string, assumed to be a format.
545 * @return string
547 function dateFormat( $usePrefs = true ) {
548 global $wgUser;
550 if( is_bool( $usePrefs ) ) {
551 if( $usePrefs ) {
552 $datePreference = $wgUser->getOption( 'date' );
553 } else {
554 $options = $this->getDefaultUserOptions();
555 $datePreference = (string)$options['date'];
557 } else {
558 $datePreference = (string)$usePrefs;
561 // return int
562 if( $datePreference == '' ) {
563 return MW_DATE_DEFAULT;
566 return $datePreference;
570 * @access public
571 * @param mixed $ts the time format which needs to be turned into a
572 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
573 * @param bool $adj whether to adjust the time output according to the
574 * user configured offset ($timecorrection)
575 * @param mixed $format true to use user's date format preference
576 * @param string $timecorrection the time offset as returned by
577 * validateTimeZone() in Special:Preferences
578 * @return string
580 function date( $ts, $adj = false, $format = true, $timecorrection = false ) {
581 global $wgUser, $wgAmericanDates;
583 if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
585 $datePreference = $this->dateFormat( $format );
586 if( $datePreference == MW_DATE_DEFAULT ) {
587 $datePreference = $wgAmericanDates ? MW_DATE_MDY : MW_DATE_DMY;
590 $month = $this->formatMonth( substr( $ts, 4, 2 ), $datePreference );
591 $day = $this->formatDay( substr( $ts, 6, 2 ), $datePreference );
592 $year = $this->formatNum( substr( $ts, 0, 4 ), true );
594 switch( $datePreference ) {
595 case MW_DATE_DMY: return "$day $month $year";
596 case MW_DATE_YMD: return "$year $month $day";
597 case MW_DATE_ISO: return substr($ts, 0, 4). '-' . substr($ts, 4, 2). '-' .substr($ts, 6, 2);
598 default: return "$month $day, $year";
603 * @access public
604 * @param mixed $ts the time format which needs to be turned into a
605 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
606 * @param bool $adj whether to adjust the time output according to the
607 * user configured offset ($timecorrection)
608 * @param mixed $format true to use user's date format preference
609 * @param string $timecorrection the time offset as returned by
610 * validateTimeZone() in Special:Preferences
611 * @return string
613 function time( $ts, $adj = false, $format = true, $timecorrection = false ) {
614 global $wgUser;
616 if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
617 $datePreference = $this->dateFormat( $format );
619 $sep = ($datePreference == MW_DATE_ISO)
620 ? ':'
621 : $this->timeSeparator( $format );
623 $t = substr( $ts, 8, 2 ) . $sep . substr( $ts, 10, 2 );
625 if ( $datePreference == MW_DATE_ISO ) {
626 $t .= $sep . substr( $ts, 12, 2 );
628 return $t;
632 * Default separator character between hours, minutes, and seconds.
633 * Will be used by Language::time() for non-ISO formats.
634 * (ISO will always use a colon.)
635 * @return string
637 function timeSeparator( $format ) {
638 return ':';
642 * String to insert between the time and the date in a combined
643 * string. Should include any relevant whitespace.
644 * @return string
646 function timeDateSeparator( $format ) {
647 return ', ';
651 * Return true if the time should display before the date.
652 * @return bool
653 * @access private
655 function timeBeforeDate() {
656 return true;
659 function formatMonth( $month, $format ) {
660 return $this->getMonthName( $month );
663 function formatDay( $day, $format ) {
664 return $this->formatNum( 0 + $day );
668 * @access public
669 * @param mixed $ts the time format which needs to be turned into a
670 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
671 * @param bool $adj whether to adjust the time output according to the
672 * user configured offset ($timecorrection)
674 * @param mixed $format what format to return, if it's false output the
675 * default one (default true)
676 * @param string $timecorrection the time offset as returned by
677 * validateTimeZone() in Special:Preferences
678 * @return string
680 function timeanddate( $ts, $adj = false, $format = true, $timecorrection = false) {
681 global $wgUser;
683 $datePreference = $this->dateFormat($format);
684 switch ( $datePreference ) {
685 case MW_DATE_ISO: return $this->date( $ts, $adj, $format, $timecorrection ) . ' ' .
686 $this->time( $ts, $adj, $format, $timecorrection );
687 default:
688 $time = $this->time( $ts, $adj, $format, $timecorrection );
689 $sep = $this->timeDateSeparator( $datePreference );
690 $date = $this->date( $ts, $adj, $format, $timecorrection );
691 return $this->timeBeforeDate( $datePreference )
692 ? $time . $sep . $date
693 : $date . $sep . $time;
697 function getMessage( $key ) {
698 global $wgAllMessagesEn;
699 return @$wgAllMessagesEn[$key];
702 function getAllMessages() {
703 global $wgAllMessagesEn;
704 return $wgAllMessagesEn;
707 function iconv( $in, $out, $string ) {
708 # For most languages, this is a wrapper for iconv
709 return iconv( $in, $out, $string );
712 function ucfirst( $string ) {
713 # For most languages, this is a wrapper for ucfirst()
714 return ucfirst( $string );
717 function uc( $str ) {
718 return strtoupper( $str );
721 function lcfirst( $s ) {
722 return strtolower( $s{0} ). substr( $s, 1 );
725 function lc( $str ) {
726 return strtolower( $str );
729 function checkTitleEncoding( $s ) {
730 global $wgInputEncoding;
732 # Check for UTF-8 URLs; Internet Explorer produces these if you
733 # type non-ASCII chars in the URL bar or follow unescaped links.
734 $ishigh = preg_match( '/[\x80-\xff]/', $s);
735 $isutf = ($ishigh ? preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
736 '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s ) : true );
738 if( ($wgInputEncoding != 'utf-8') and $ishigh and $isutf )
739 return @iconv( 'UTF-8', $wgInputEncoding, $s );
741 if( ($wgInputEncoding == 'utf-8') and $ishigh and !$isutf )
742 return utf8_encode( $s );
744 # Other languages can safely leave this function, or replace
745 # it with one to detect and convert another legacy encoding.
746 return $s;
750 * Some languages have special punctuation to strip out
751 * or characters which need to be converted for MySQL's
752 * indexing to grok it correctly. Make such changes here.
754 * @param string $in
755 * @return string
757 function stripForSearch( $in ) {
758 return strtolower( $in );
761 function convertForSearchResult( $termsArray ) {
762 # some languages, e.g. Chinese, need to do a conversion
763 # in order for search results to be displayed correctly
764 return $termsArray;
768 * Get the first character of a string. In ASCII, return
769 * first byte of the string. UTF8 and others have to
770 * overload this.
772 * @param string $s
773 * @return string
775 function firstChar( $s ) {
776 return $s[0];
779 function initEncoding() {
780 # Some languages may have an alternate char encoding option
781 # (Esperanto X-coding, Japanese furigana conversion, etc)
782 # If this language is used as the primary content language,
783 # an override to the defaults can be set here on startup.
784 #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
787 function setAltEncoding() {
788 # Some languages may have an alternate char encoding option
789 # (Esperanto X-coding, Japanese furigana conversion, etc)
790 # If 'altencoding' is checked in user prefs, this gives a
791 # chance to swap out the default encoding settings.
792 #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
795 function recodeForEdit( $s ) {
796 # For some languages we'll want to explicitly specify
797 # which characters make it into the edit box raw
798 # or are converted in some way or another.
799 # Note that if wgOutputEncoding is different from
800 # wgInputEncoding, this text will be further converted
801 # to wgOutputEncoding.
802 global $wgInputEncoding, $wgEditEncoding;
803 if( $wgEditEncoding == '' or
804 $wgEditEncoding == $wgInputEncoding ) {
805 return $s;
806 } else {
807 return $this->iconv( $wgInputEncoding, $wgEditEncoding, $s );
811 function recodeInput( $s ) {
812 # Take the previous into account.
813 global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
814 if($wgEditEncoding != "") {
815 $enc = $wgEditEncoding;
816 } else {
817 $enc = $wgOutputEncoding;
819 if( $enc == $wgInputEncoding ) {
820 return $s;
821 } else {
822 return $this->iconv( $enc, $wgInputEncoding, $s );
827 * For right-to-left language support
829 * @return bool
831 function isRTL() { return false; }
834 * To allow "foo[[bar]]" to extend the link over the whole word "foobar"
836 * @return bool
838 function linkPrefixExtension() { return false; }
841 function &getMagicWords() {
842 global $wgMagicWordsEn;
843 return $wgMagicWordsEn;
846 # Fill a MagicWord object with data from here
847 function getMagic( &$mw ) {
848 $raw = $this->getMagicWords();
850 wfRunHooks( 'LanguageGetMagic', array( &$raw ) );
852 if( !isset( $raw[$mw->mId] ) ) {
853 # Fall back to English if local list is incomplete
854 $raw =& Language::getMagicWords();
856 $rawEntry = $raw[$mw->mId];
857 $mw->mCaseSensitive = $rawEntry[0];
858 $mw->mSynonyms = array_slice( $rawEntry, 1 );
862 * Italic is unsuitable for some languages
864 * @access public
866 * @param string $text The text to be emphasized.
867 * @return string
869 function emphasize( $text ) {
870 return "<em>$text</em>";
874 * This function enables formatting of numbers, it should only come
875 * into effect when the $wgTranslateNumerals variable is TRUE.
877 * Normally we output all numbers in plain en_US style, that is
878 * 293,291.235 for twohundredninetythreethousand-twohundredninetyone
879 * point twohundredthirtyfive. However this is not sutable for all
880 * languages, some such as Pakaran want ੨੯੩,੨੯੫.੨੩੫ and others such as
881 * Icelandic just want to use commas instead of dots, and dots instead
882 * of commas like "293.291,235".
884 * An example of this function being called:
885 * <code>
886 * wfMsg( 'message', $wgLang->formatNum( $num ) )
887 * </code>
889 * See LanguageGu.php for the Gujarati implementation and
890 * LanguageIs.php for the , => . and . => , implementation.
892 * @todo check if it's viable to use localeconv() for the decimal
893 * seperator thing.
894 * @access public
895 * @param mixed $number the string to be formatted, should be an integer or
896 * a floating point number.
897 * @param bool $year are we being passed a year? (turns off commafication)
898 * @return mixed whatever we're fed if it's a year, a string otherwise.
900 function formatNum( $number, $year = false ) {
901 return $year ? $number : $this->commafy($number);
905 * Adds commas to a given number
907 * @param mixed $_
908 * @return string
910 function commafy($_) {
911 return strrev((string)preg_replace('/(\d{3})(?=\d)(?!\d*\.)/','$1,',strrev($_)));
915 * For the credit list in includes/Credits.php (action=credits)
917 * @param array $l
918 * @return string
920 function listToText( $l ) {
921 $s = '';
922 $m = count($l) - 1;
923 for ($i = $m; $i >= 0; $i--) {
924 if ($i == $m) {
925 $s = $l[$i];
926 } else if ($i == $m - 1) {
927 $s = $l[$i] . ' ' . wfMsg('and') . ' ' . $s;
928 } else {
929 $s = $l[$i] . ', ' . $s;
932 return $s;
935 # Crop a string from the beginning or end to a certain number of bytes.
936 # (Bytes are used because our storage has limited byte lengths for some
937 # columns in the database.) Multibyte charsets will need to make sure that
938 # only whole characters are included!
940 # $length does not include the optional ellipsis.
941 # If $length is negative, snip from the beginning
942 function truncate( $string, $length, $ellipsis = '' ) {
943 if( $length == 0 ) {
944 return $ellipsis;
946 if ( strlen( $string ) <= abs( $length ) ) {
947 return $string;
949 if( $length > 0 ) {
950 $string = substr( $string, 0, $length );
951 return $string . $ellipsis;
952 } else {
953 $string = substr( $string, $length );
954 return $ellipsis . $string;
959 * Grammatical transformations, needed for inflected languages
960 * Invoked by putting {{grammar:case|word}} in a message
962 * @param string $word
963 * @param string $case
964 * @return string
966 function convertGrammar( $word, $case ) {
967 return $word;
971 * Plural form transformations, needed for some languages.
972 * For example, where are 3 form of plural in Russian and Polish,
973 * depending on "count mod 10". See [[w:Plural]]
974 * For English it is pretty simple.
976 * Invoked by putting {{plural:count|wordform1|wordform2}}
977 * or {{plural:count|wordform1|wordform2|wordform3}}
979 * Example: {{plural:{{NUMBEROFARTICLES}}|article|articles}}
981 * @param integer $count
982 * @param string $wordform1
983 * @param string $wordform2
984 * @param string $wordform3 (optional)
985 * @return string
987 function convertPlural( $count, $wordform1, $wordform2, $wordform3) {
988 return $count == '1' ? $wordform1 : $wordform2;
992 * For translaing of expiry times
993 * @param string The validated block time in English
994 * @return Somehow translated block time
995 * @see LanguageFi.php for example implementation
997 function translateBlockExpiry( $str ) {
999 $scBlockExpiryOptions = wfMsg( 'ipboptions' );
1001 if ( $scBlockExpiryOptions == '-') {
1002 return $str;
1005 foreach (explode(',', $scBlockExpiryOptions) as $option) {
1006 if ( strpos($option, ":") === false )
1007 continue;
1008 list($show, $value) = explode(":", $option);
1009 if ( strcmp ( $str, $value) == 0 )
1010 return '<span title="' . htmlspecialchars($str). '">' .
1011 htmlspecialchars( trim( $show ) ) . '</span>';
1014 return $str;
1018 * languages like Chinese need to be segmented in order for the diff
1019 * to be of any use
1021 * @param string $text
1022 * @return string
1024 function segmentForDiff( $text ) {
1025 return $text;
1029 * and unsegment to show the result
1031 * @param string $text
1032 * @return string
1034 function unsegmentForDiff( $text ) {
1035 return $text;
1038 # convert text to different variants of a language.
1039 function convert( $text, $isTitle = false) {
1040 return $this->mConverter->convert($text, $isTitle);
1043 # Convert text from within Parser
1044 function parserConvert( $text, &$parser ) {
1045 return $this->mConverter->parserConvert( $text, $parser );
1049 * Perform output conversion on a string, and encode for safe HTML output.
1050 * @param string $text
1051 * @param bool $isTitle -- wtf?
1052 * @return string
1053 * @todo this should get integrated somewhere sane
1055 function convertHtml( $text, $isTitle = false ) {
1056 return htmlspecialchars( $this->convert( $text, $isTitle ) );
1059 function convertCategoryKey( $key ) {
1060 return $this->mConverter->convertCategoryKey( $key );
1064 * get the list of variants supported by this langauge
1065 * see sample implementation in LanguageZh.php
1067 * @return array an array of language codes
1069 function getVariants() {
1070 return $this->mConverter->getVariants();
1074 function getPreferredVariant() {
1075 return $this->mConverter->getPreferredVariant();
1079 * if a language supports multiple variants, it is
1080 * possible that non-existing link in one variant
1081 * actually exists in another variant. this function
1082 * tries to find it. See e.g. LanguageZh.php
1084 * @param string $link the name of the link
1085 * @param mixed $nt the title object of the link
1086 * @return null the input parameters may be modified upon return
1088 function findVariantLink( &$link, &$nt ) {
1089 $this->mConverter->findVariantLink($link, $nt);
1093 * returns language specific options used by User::getPageRenderHash()
1094 * for example, the preferred language variant
1096 * @return string
1097 * @access public
1099 function getExtraHashOptions() {
1100 return $this->mConverter->getExtraHashOptions();
1104 * for languages that support multiple variants, the title of an
1105 * article may be displayed differently in different variants. this
1106 * function returns the apporiate title defined in the body of the article.
1108 * @return string
1110 function getParsedTitle() {
1111 return $this->mConverter->getParsedTitle();
1115 * Enclose a string with the "no conversion" tag. This is used by
1116 * various functions in the Parser
1118 * @param string $text text to be tagged for no conversion
1119 * @return string the tagged text
1121 function markNoConversion( $text ) {
1122 return $this->mConverter->markNoConversion( $text );
1126 * A regular expression to match legal word-trailing characters
1127 * which should be merged onto a link of the form [[foo]]bar.
1129 * @return string
1130 * @access public
1132 function linkTrail() {
1133 return $this->getMessage( 'linktrail' );
1136 function getLangObj() {
1137 return $this;
1141 * Get the RFC 3066 code for this language object
1143 function getCode() {
1144 return str_replace( '_', '-', strtolower( substr( get_class( $this ), 8 ) ) );
1150 # FIXME: Merge all UTF-8 support code into Language base class.
1151 # We no longer support Latin-1 charset.
1152 require_once( 'LanguageUtf8.php' );
1154 # This should fail gracefully if there's not a localization available
1155 wfSuppressWarnings();
1156 // Preload base classes to work around APC/PHP5 bug
1157 include_once( 'Language' . str_replace( '-', '_', ucfirst( $wgLanguageCode ) ) . '.deps.php' );
1158 include_once( 'Language' . str_replace( '-', '_', ucfirst( $wgLanguageCode ) ) . '.php' );
1159 wfRestoreWarnings();