* Add <ol> to the list of block elements for doBlockLevels; avoids <p>s being intersp...
[mediawiki.git] / languages / Language.php
blobb77344abe112b8517ae850a8950cfe9c98b14605
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 'wllimit' => 250,
66 'highlightbroken' => 1,
67 'stubthreshold' => 0,
68 'previewontop' => 1,
69 'editsection' => 1,
70 'editsectiononrightclick'=> 0,
71 'showtoc' => 1,
72 'showtoolbar' => 1,
73 'date' => 0,
74 'imagesize' => 2,
75 'thumbsize' => 2,
76 'rememberpassword' => 0,
77 'enotifwatchlistpages' => 0,
78 'enotifusertalkpages' => 1,
79 'enotifminoredits' => 0,
80 'enotifrevealaddr' => 0,
81 'shownumberswatching' => 1,
82 'fancysig' => 0,
83 'externaleditor' => 0,
84 'externaldiff' => 0,
85 'showjumplinks' => 1,
86 'numberheadings' => 0,
87 'uselivepreview' => 0,
88 'watchlistdays' => 3.0,
91 /* private */ $wgQuickbarSettingsEn = array(
92 'None', 'Fixed left', 'Fixed right', 'Floating left', 'Floating right'
95 /* private */ $wgSkinNamesEn = array(
96 'standard' => 'Classic',
97 'nostalgia' => 'Nostalgia',
98 'cologneblue' => 'Cologne Blue',
99 'davinci' => 'DaVinci',
100 'mono' => 'Mono',
101 'monobook' => 'MonoBook',
102 'myskin' => 'MySkin',
103 'chick' => 'Chick'
106 /* private */ $wgMathNamesEn = array(
107 MW_MATH_PNG => 'mw_math_png',
108 MW_MATH_SIMPLE => 'mw_math_simple',
109 MW_MATH_HTML => 'mw_math_html',
110 MW_MATH_SOURCE => 'mw_math_source',
111 MW_MATH_MODERN => 'mw_math_modern',
112 MW_MATH_MATHML => 'mw_math_mathml'
116 * Whether to use user or default setting in Language::date()
118 * NOTE: the array string values are no longer important!
119 * The actual date format functions are now called for the selection in
120 * Special:Preferences, and the 'datedefault' message for MW_DATE_DEFAULT.
122 * The array keys make up the set of formats which this language allows
123 * the user to select. It's exposed via Language::getDateFormats().
125 * @private
127 $wgDateFormatsEn = array(
128 MW_DATE_DEFAULT => 'No preference',
129 MW_DATE_DMY => '16:12, 15 January 2001',
130 MW_DATE_MDY => '16:12, January 15, 2001',
131 MW_DATE_YMD => '16:12, 2001 January 15',
132 MW_DATE_ISO => '2001-01-15 16:12:34'
135 /* private */ $wgUserTogglesEn = array(
136 'highlightbroken',
137 'justify',
138 'hideminor',
139 'extendwatchlist',
140 'usenewrc',
141 'numberheadings',
142 'showtoolbar',
143 'editondblclick',
144 'editsection',
145 'editsectiononrightclick',
146 'showtoc',
147 'rememberpassword',
148 'editwidth',
149 'watchcreations',
150 'watchdefault',
151 'minordefault',
152 'previewontop',
153 'previewonfirst',
154 'nocache',
155 'enotifwatchlistpages',
156 'enotifusertalkpages',
157 'enotifminoredits',
158 'enotifrevealaddr',
159 'shownumberswatching',
160 'fancysig',
161 'externaleditor',
162 'externaldiff',
163 'showjumplinks',
164 'uselivepreview',
165 'autopatrol',
166 'forceeditsummary',
167 'watchlisthideown',
168 'watchlisthidebots',
171 /* private */ $wgBookstoreListEn = array(
172 'AddALL' => 'http://www.addall.com/New/Partner.cgi?query=$1&type=ISBN',
173 'PriceSCAN' => 'http://www.pricescan.com/books/bookDetail.asp?isbn=$1',
174 'Barnes & Noble' => 'http://search.barnesandnoble.com/bookSearch/isbnInquiry.asp?isbn=$1',
175 'Amazon.com' => 'http://www.amazon.com/exec/obidos/ISBN=$1'
178 # Read language names
179 global $wgLanguageNames;
180 /** */
181 require_once( 'Names.php' );
183 $wgLanguageNamesEn =& $wgLanguageNames;
186 /* private */ $wgWeekdayNamesEn = array(
187 'sunday', 'monday', 'tuesday', 'wednesday', 'thursday',
188 'friday', 'saturday'
192 /* private */ $wgMonthNamesEn = array(
193 'january', 'february', 'march', 'april', 'may_long', 'june',
194 'july', 'august', 'september', 'october', 'november',
195 'december'
197 /* private */ $wgMonthNamesGenEn = array(
198 'january-gen', 'february-gen', 'march-gen', 'april-gen', 'may-gen', 'june-gen',
199 'july-gen', 'august-gen', 'september-gen', 'october-gen', 'november-gen',
200 'december-gen'
203 /* private */ $wgMonthAbbreviationsEn = array(
204 'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug',
205 'sep', 'oct', 'nov', 'dec'
208 # Note to translators:
209 # Please include the English words as synonyms. This allows people
210 # from other wikis to contribute more easily.
212 /* private */ $wgMagicWordsEn = array(
213 # ID CASE SYNONYMS
214 MAG_REDIRECT => array( 0, '#REDIRECT' ),
215 MAG_NOTOC => array( 0, '__NOTOC__' ),
216 MAG_FORCETOC => array( 0, '__FORCETOC__' ),
217 MAG_TOC => array( 0, '__TOC__' ),
218 MAG_NOEDITSECTION => array( 0, '__NOEDITSECTION__' ),
219 MAG_START => array( 0, '__START__' ),
220 MAG_CURRENTMONTH => array( 1, 'CURRENTMONTH' ),
221 MAG_CURRENTMONTHNAME => array( 1, 'CURRENTMONTHNAME' ),
222 MAG_CURRENTMONTHNAMEGEN => array( 1, 'CURRENTMONTHNAMEGEN' ),
223 MAG_CURRENTMONTHABBREV => array( 1, 'CURRENTMONTHABBREV' ),
224 MAG_CURRENTDAY => array( 1, 'CURRENTDAY' ),
225 MAG_CURRENTDAY2 => array( 1, 'CURRENTDAY2' ),
226 MAG_CURRENTDAYNAME => array( 1, 'CURRENTDAYNAME' ),
227 MAG_CURRENTYEAR => array( 1, 'CURRENTYEAR' ),
228 MAG_CURRENTTIME => array( 1, 'CURRENTTIME' ),
229 MAG_NUMBEROFPAGES => array( 1, 'NUMBEROFPAGES' ),
230 MAG_NUMBEROFARTICLES => array( 1, 'NUMBEROFARTICLES' ),
231 MAG_NUMBEROFFILES => array( 1, 'NUMBEROFFILES' ),
232 MAG_NUMBEROFUSERS => array( 1, 'NUMBEROFUSERS' ),
233 MAG_PAGENAME => array( 1, 'PAGENAME' ),
234 MAG_PAGENAMEE => array( 1, 'PAGENAMEE' ),
235 MAG_NAMESPACE => array( 1, 'NAMESPACE' ),
236 MAG_NAMESPACEE => array( 1, 'NAMESPACEE' ),
237 MAG_TALKSPACE => array( 1, 'TALKSPACE' ),
238 MAG_TALKSPACEE => array( 1, 'TALKSPACEE' ),
239 MAG_SUBJECTSPACE => array( 1, 'SUBJECTSPACE', 'ARTICLESPACE' ),
240 MAG_SUBJECTSPACEE => array( 1, 'SUBJECTSPACEE', 'ARTICLESPACEE' ),
241 MAG_FULLPAGENAME => array( 1, 'FULLPAGENAME' ),
242 MAG_FULLPAGENAMEE => array( 1, 'FULLPAGENAMEE' ),
243 MAG_SUBPAGENAME => array( 1, 'SUBPAGENAME' ),
244 MAG_SUBPAGENAMEE => array( 1, 'SUBPAGENAMEE' ),
245 MAG_BASEPAGENAME => array( 1, 'BASEPAGENAME' ),
246 MAG_BASEPAGENAMEE => array( 1, 'BASEPAGENAMEE' ),
247 MAG_TALKPAGENAME => array( 1, 'TALKPAGENAME' ),
248 MAG_TALKPAGENAMEE => array( 1, 'TALKPAGENAMEE' ),
249 MAG_SUBJECTPAGENAME => array( 1, 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ),
250 MAG_SUBJECTPAGENAMEE => array( 1, 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ),
251 MAG_MSG => array( 0, 'MSG:' ),
252 MAG_SUBST => array( 0, 'SUBST:' ),
253 MAG_MSGNW => array( 0, 'MSGNW:' ),
254 MAG_END => array( 0, '__END__' ),
255 MAG_IMG_THUMBNAIL => array( 1, 'thumbnail', 'thumb' ),
256 MAG_IMG_MANUALTHUMB => array( 1, 'thumbnail=$1', 'thumb=$1'),
257 MAG_IMG_RIGHT => array( 1, 'right' ),
258 MAG_IMG_LEFT => array( 1, 'left' ),
259 MAG_IMG_NONE => array( 1, 'none' ),
260 MAG_IMG_WIDTH => array( 1, '$1px' ),
261 MAG_IMG_CENTER => array( 1, 'center', 'centre' ),
262 MAG_IMG_FRAMED => array( 1, 'framed', 'enframed', 'frame' ),
263 MAG_INT => array( 0, 'INT:' ),
264 MAG_SITENAME => array( 1, 'SITENAME' ),
265 MAG_NS => array( 0, 'NS:' ),
266 MAG_LOCALURL => array( 0, 'LOCALURL:' ),
267 MAG_LOCALURLE => array( 0, 'LOCALURLE:' ),
268 MAG_SERVER => array( 0, 'SERVER' ),
269 MAG_SERVERNAME => array( 0, 'SERVERNAME' ),
270 MAG_SCRIPTPATH => array( 0, 'SCRIPTPATH' ),
271 MAG_GRAMMAR => array( 0, 'GRAMMAR:' ),
272 MAG_NOTITLECONVERT => array( 0, '__NOTITLECONVERT__', '__NOTC__'),
273 MAG_NOCONTENTCONVERT => array( 0, '__NOCONTENTCONVERT__', '__NOCC__'),
274 MAG_CURRENTWEEK => array( 1, 'CURRENTWEEK' ),
275 MAG_CURRENTDOW => array( 1, 'CURRENTDOW' ),
276 MAG_REVISIONID => array( 1, 'REVISIONID' ),
277 MAG_PLURAL => array( 0, 'PLURAL:' ),
278 MAG_FULLURL => array( 0, 'FULLURL:' ),
279 MAG_FULLURLE => array( 0, 'FULLURLE:' ),
280 MAG_LCFIRST => array( 0, 'LCFIRST:' ),
281 MAG_UCFIRST => array( 0, 'UCFIRST:' ),
282 MAG_LC => array( 0, 'LC:' ),
283 MAG_UC => array( 0, 'UC:' ),
284 MAG_RAW => array( 0, 'RAW:' ),
285 MAG_DISPLAYTITLE => array( 1, 'DISPLAYTITLE' ),
286 MAG_RAWSUFFIX => array( 1, 'R' ),
287 MAG_NEWSECTIONLINK => array( 1, '__NEWSECTIONLINK__' ),
288 MAG_CURRENTVERSION => array( 1, 'CURRENTVERSION' ),
289 MAG_URLENCODE => array( 0, 'URLENCODE:' ),
290 MAG_CURRENTTIMESTAMP => array( 1, 'CURRENTTIMESTAMP' ),
291 MAG_DIRECTIONMARK => array( 1, 'DIRECTIONMARK', 'DIRMARK' ),
292 MAG_LANGUAGE => array( 0, '#LANGUAGE:' ),
295 if (!$wgCachedMessageArrays) {
296 require_once('Messages.php');
299 /* a fake language converter */
300 class fakeConverter {
301 var $mLang;
302 function fakeConverter($langobj) {$this->mLang = $langobj;}
303 function convert($t, $i) {return $t;}
304 function parserConvert($t, $p) {return $t;}
305 function getVariants() { return array( $this->mLang->getCode() ); }
306 function getPreferredVariant() {return $this->mLang->getCode(); }
307 function findVariantLink(&$l, &$n) {}
308 function getExtraHashOptions() {return '';}
309 function getParsedTitle() {return '';}
310 function markNoConversion($text) {return $text;}
311 function convertCategoryKey( $key ) {return $key; }
315 #--------------------------------------------------------------------------
316 # Internationalisation code
317 #--------------------------------------------------------------------------
319 class Language {
320 var $mConverter;
321 function Language() {
322 $this->mConverter = new fakeConverter($this);
326 * Exports the default user options as defined in
327 * $wgDefaultUserOptionsEn, user preferences can override some of these
328 * depending on what's in (Local|Default)Settings.php and some defines.
330 * @return array
332 function getDefaultUserOptions() {
333 global $wgDefaultUserOptionsEn ;
334 return $wgDefaultUserOptionsEn ;
338 * Exports $wgBookstoreListEn
339 * @return array
341 function getBookstoreList() {
342 global $wgBookstoreListEn ;
343 return $wgBookstoreListEn ;
347 * @return array
349 function getNamespaces() {
350 global $wgNamespaceNamesEn;
351 return $wgNamespaceNamesEn;
355 * A convenience function that returns the same thing as
356 * getNamespaces() except with the array values changed to ' '
357 * where it found '_', useful for producing output to be displayed
358 * e.g. in <select> forms.
360 * @return array
362 function getFormattedNamespaces() {
363 $ns = $this->getNamespaces();
364 foreach($ns as $k => $v) {
365 $ns[$k] = strtr($v, '_', ' ');
367 return $ns;
371 * Get a namespace value by key
372 * <code>
373 * $mw_ns = $wgContLang->getNsText( NS_MEDIAWIKI );
374 * echo $mw_ns; // prints 'MediaWiki'
375 * </code>
377 * @param int $index the array key of the namespace to return
378 * @return mixed, string if the namespace value exists, otherwise false
380 function getNsText( $index ) {
381 $ns = $this->getNamespaces();
382 return isset( $ns[$index] ) ? $ns[$index] : false;
386 * A convenience function that returns the same thing as
387 * getNsText() except with '_' changed to ' ', useful for
388 * producing output.
390 * @return array
392 function getFormattedNsText( $index ) {
393 $ns = $this->getNsText( $index );
394 return strtr($ns, '_', ' ');
398 * Get a namespace key by value, case insensetive.
400 * @param string $text
401 * @return mixed An integer if $text is a valid value otherwise false
403 function getNsIndex( $text ) {
404 $ns = $this->getNamespaces();
406 foreach ( $ns as $i => $n ) {
407 if ( strcasecmp( $n, $text ) == 0)
408 return $i;
410 return false;
414 * short names for language variants used for language conversion links.
416 * @param string $code
417 * @return string
419 function getVariantname( $code ) {
420 return wfMsg( "variantname-$code" );
423 function specialPage( $name ) {
424 return $this->getNsText(NS_SPECIAL) . ':' . $name;
427 function getQuickbarSettings() {
428 global $wgQuickbarSettingsEn;
429 return $wgQuickbarSettingsEn;
432 function getSkinNames() {
433 global $wgSkinNamesEn;
434 return $wgSkinNamesEn;
437 function getMathNames() {
438 global $wgMathNamesEn;
439 return $wgMathNamesEn;
442 function getDateFormats() {
443 global $wgDateFormatsEn;
444 return $wgDateFormatsEn;
447 function getUserToggles() {
448 global $wgUserTogglesEn;
449 return $wgUserTogglesEn;
452 function getUserToggle( $tog ) {
453 return wfMsg( "tog-$tog" );
456 function getLanguageNames() {
457 global $wgLanguageNamesEn;
458 return $wgLanguageNamesEn;
461 function getLanguageName( $code ) {
462 global $wgLanguageNamesEn;
463 if ( ! array_key_exists( $code, $wgLanguageNamesEn ) ) {
464 return '';
466 return $wgLanguageNamesEn[$code];
469 function getMonthName( $key ) {
470 global $wgMonthNamesEn, $wgContLang;
471 // see who called us and use the correct message function
472 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
473 return wfMsgForContent($wgMonthNamesEn[$key-1]);
474 else
475 return wfMsg($wgMonthNamesEn[$key-1]);
478 /* by default we just return base form */
479 function getMonthNameGen( $key ) {
480 return $this->getMonthName( $key );
483 function getMonthAbbreviation( $key ) {
484 global $wgMonthAbbreviationsEn, $wgContLang;
485 // see who called us and use the correct message function
486 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
487 return wfMsgForContent(@$wgMonthAbbreviationsEn[$key-1]);
488 else
489 return wfMsg(@$wgMonthAbbreviationsEn[$key-1]);
492 function getWeekdayName( $key ) {
493 global $wgWeekdayNamesEn, $wgContLang;
494 // see who called us and use the correct message function
495 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
496 return wfMsgForContent($wgWeekdayNamesEn[$key-1]);
497 else
498 return wfMsg($wgWeekdayNamesEn[$key-1]);
502 * Used by date() and time() to adjust the time output.
503 * @public
504 * @param int $ts the time in date('YmdHis') format
505 * @param mixed $tz adjust the time by this amount (default false,
506 * mean we get user timecorrection setting)
507 * @return int
510 function userAdjust( $ts, $tz = false ) {
511 global $wgUser, $wgLocalTZoffset;
513 if (!$tz) {
514 $tz = $wgUser->getOption( 'timecorrection' );
517 # minutes and hours differences:
518 $minDiff = 0;
519 $hrDiff = 0;
521 if ( $tz === '' ) {
522 # Global offset in minutes.
523 if( isset($wgLocalTZoffset) ) {
524 $hrDiff = $wgLocalTZoffset % 60;
525 $minDiff = $wgLocalTZoffset - ($hrDiff * 60);
527 } elseif ( strpos( $tz, ':' ) !== false ) {
528 $tzArray = explode( ':', $tz );
529 $hrDiff = intval($tzArray[0]);
530 $minDiff = intval($hrDiff < 0 ? -$tzArray[1] : $tzArray[1]);
531 } else {
532 $hrDiff = intval( $tz );
535 # No difference ? Return time unchanged
536 if ( 0 == $hrDiff && 0 == $minDiff ) { return $ts; }
538 # Generate an adjusted date
539 $t = mktime( (
540 (int)substr( $ts, 8, 2) ) + $hrDiff, # Hours
541 (int)substr( $ts, 10, 2 ) + $minDiff, # Minutes
542 (int)substr( $ts, 12, 2 ), # Seconds
543 (int)substr( $ts, 4, 2 ), # Month
544 (int)substr( $ts, 6, 2 ), # Day
545 (int)substr( $ts, 0, 4 ) ); #Year
546 return date( 'YmdHis', $t );
550 * This is meant to be used by time(), date(), and timeanddate() to get
551 * the date preference they're supposed to use, it should be used in
552 * all children.
554 *<code>
555 * function timeanddate([...], $format = true) {
556 * $datePreference = $this->dateFormat($format);
557 * [...]
558 *</code>
560 * @param mixed $usePrefs: if true, the user's preference is used
561 * if false, the site/language default is used
562 * if int/string, assumed to be a format.
563 * @return string
565 function dateFormat( $usePrefs = true ) {
566 global $wgUser;
568 if( is_bool( $usePrefs ) ) {
569 if( $usePrefs ) {
570 $datePreference = $wgUser->getOption( 'date' );
571 } else {
572 $options = $this->getDefaultUserOptions();
573 $datePreference = (string)$options['date'];
575 } else {
576 $datePreference = (string)$usePrefs;
579 // return int
580 if( $datePreference == '' ) {
581 return MW_DATE_DEFAULT;
584 return $datePreference;
588 * @public
589 * @param mixed $ts the time format which needs to be turned into a
590 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
591 * @param bool $adj whether to adjust the time output according to the
592 * user configured offset ($timecorrection)
593 * @param mixed $format true to use user's date format preference
594 * @param string $timecorrection the time offset as returned by
595 * validateTimeZone() in Special:Preferences
596 * @return string
598 function date( $ts, $adj = false, $format = true, $timecorrection = false ) {
599 global $wgUser, $wgAmericanDates;
601 if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
603 $datePreference = $this->dateFormat( $format );
604 if( $datePreference == MW_DATE_DEFAULT ) {
605 $datePreference = $wgAmericanDates ? MW_DATE_MDY : MW_DATE_DMY;
608 $month = $this->formatMonth( substr( $ts, 4, 2 ), $datePreference );
609 $day = $this->formatDay( substr( $ts, 6, 2 ), $datePreference );
610 $year = $this->formatNum( substr( $ts, 0, 4 ), true );
612 switch( $datePreference ) {
613 case MW_DATE_DMY: return "$day $month $year";
614 case MW_DATE_YMD: return "$year $month $day";
615 case MW_DATE_ISO: return substr($ts, 0, 4). '-' . substr($ts, 4, 2). '-' .substr($ts, 6, 2);
616 default: return "$month $day, $year";
621 * @public
622 * @param mixed $ts the time format which needs to be turned into a
623 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
624 * @param bool $adj whether to adjust the time output according to the
625 * user configured offset ($timecorrection)
626 * @param mixed $format true to use user's date format preference
627 * @param string $timecorrection the time offset as returned by
628 * validateTimeZone() in Special:Preferences
629 * @return string
631 function time( $ts, $adj = false, $format = true, $timecorrection = false ) {
632 global $wgUser;
634 if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
635 $datePreference = $this->dateFormat( $format );
637 $sep = $this->timeSeparator( $format );
639 $hh = substr( $ts, 8, 2 );
640 $mm = substr( $ts, 10, 2 );
641 $ss = substr( $ts, 12, 2 );
643 if ( $datePreference != MW_DATE_ISO ) {
644 $hh = $this->formatNum( $hh, true );
645 $mm = $this->formatNum( $mm, true );
646 //$ss = $this->formatNum( $ss, true );
647 return $hh . $sep . $mm;
648 } else {
649 return $hh . ':' . $mm . ':' . $ss;
654 * Default separator character between hours, minutes, and seconds.
655 * Will be used by Language::time() for non-ISO formats.
656 * (ISO will always use a colon.)
657 * @return string
659 function timeSeparator( $format ) {
660 return ':';
664 * String to insert between the time and the date in a combined
665 * string. Should include any relevant whitespace.
666 * @return string
668 function timeDateSeparator( $format ) {
669 return ', ';
673 * Return true if the time should display before the date.
674 * @return bool
675 * @private
677 function timeBeforeDate() {
678 return true;
681 function formatMonth( $month, $format ) {
682 return $this->getMonthName( $month );
685 function formatDay( $day, $format ) {
686 return $this->formatNum( 0 + $day, true );
690 * @public
691 * @param mixed $ts the time format which needs to be turned into a
692 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
693 * @param bool $adj whether to adjust the time output according to the
694 * user configured offset ($timecorrection)
696 * @param mixed $format what format to return, if it's false output the
697 * default one (default true)
698 * @param string $timecorrection the time offset as returned by
699 * validateTimeZone() in Special:Preferences
700 * @return string
702 function timeanddate( $ts, $adj = false, $format = true, $timecorrection = false) {
703 global $wgUser;
705 $datePreference = $this->dateFormat($format);
706 switch ( $datePreference ) {
707 case MW_DATE_ISO: return $this->date( $ts, $adj, $format, $timecorrection ) . ' ' .
708 $this->time( $ts, $adj, $format, $timecorrection );
709 default:
710 $time = $this->time( $ts, $adj, $format, $timecorrection );
711 $sep = $this->timeDateSeparator( $datePreference );
712 $date = $this->date( $ts, $adj, $format, $timecorrection );
713 return $this->timeBeforeDate( $datePreference )
714 ? $time . $sep . $date
715 : $date . $sep . $time;
719 function getMessage( $key ) {
720 global $wgAllMessagesEn;
721 return @$wgAllMessagesEn[$key];
724 function getAllMessages() {
725 global $wgAllMessagesEn;
726 return $wgAllMessagesEn;
729 function iconv( $in, $out, $string ) {
730 # For most languages, this is a wrapper for iconv
731 return iconv( $in, $out, $string );
734 function ucfirst( $string ) {
735 # For most languages, this is a wrapper for ucfirst()
736 return ucfirst( $string );
739 function uc( $str ) {
740 return strtoupper( $str );
743 function lcfirst( $s ) {
744 return strtolower( $s{0} ). substr( $s, 1 );
747 function lc( $str ) {
748 return strtolower( $str );
751 function checkTitleEncoding( $s ) {
752 global $wgInputEncoding;
754 # Check for UTF-8 URLs; Internet Explorer produces these if you
755 # type non-ASCII chars in the URL bar or follow unescaped links.
756 $ishigh = preg_match( '/[\x80-\xff]/', $s);
757 $isutf = ($ishigh ? preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
758 '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s ) : true );
760 if( ($wgInputEncoding != 'utf-8') and $ishigh and $isutf )
761 return @iconv( 'UTF-8', $wgInputEncoding, $s );
763 if( ($wgInputEncoding == 'utf-8') and $ishigh and !$isutf )
764 return utf8_encode( $s );
766 # Other languages can safely leave this function, or replace
767 # it with one to detect and convert another legacy encoding.
768 return $s;
772 * Some languages have special punctuation to strip out
773 * or characters which need to be converted for MySQL's
774 * indexing to grok it correctly. Make such changes here.
776 * @param string $in
777 * @return string
779 function stripForSearch( $in ) {
780 return strtolower( $in );
783 function convertForSearchResult( $termsArray ) {
784 # some languages, e.g. Chinese, need to do a conversion
785 # in order for search results to be displayed correctly
786 return $termsArray;
790 * Get the first character of a string. In ASCII, return
791 * first byte of the string. UTF8 and others have to
792 * overload this.
794 * @param string $s
795 * @return string
797 function firstChar( $s ) {
798 return $s[0];
801 function initEncoding() {
802 # Some languages may have an alternate char encoding option
803 # (Esperanto X-coding, Japanese furigana conversion, etc)
804 # If this language is used as the primary content language,
805 # an override to the defaults can be set here on startup.
806 #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
809 function setAltEncoding() {
810 # Some languages may have an alternate char encoding option
811 # (Esperanto X-coding, Japanese furigana conversion, etc)
812 # If 'altencoding' is checked in user prefs, this gives a
813 # chance to swap out the default encoding settings.
814 #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
817 function recodeForEdit( $s ) {
818 # For some languages we'll want to explicitly specify
819 # which characters make it into the edit box raw
820 # or are converted in some way or another.
821 # Note that if wgOutputEncoding is different from
822 # wgInputEncoding, this text will be further converted
823 # to wgOutputEncoding.
824 global $wgInputEncoding, $wgEditEncoding;
825 if( $wgEditEncoding == '' or
826 $wgEditEncoding == $wgInputEncoding ) {
827 return $s;
828 } else {
829 return $this->iconv( $wgInputEncoding, $wgEditEncoding, $s );
833 function recodeInput( $s ) {
834 # Take the previous into account.
835 global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
836 if($wgEditEncoding != "") {
837 $enc = $wgEditEncoding;
838 } else {
839 $enc = $wgOutputEncoding;
841 if( $enc == $wgInputEncoding ) {
842 return $s;
843 } else {
844 return $this->iconv( $enc, $wgInputEncoding, $s );
849 * For right-to-left language support
851 * @return bool
853 function isRTL() { return false; }
854 function getDirMark() { return $this->isRTL() ? '&rlm;' : '&lrm;'; }
857 * To allow "foo[[bar]]" to extend the link over the whole word "foobar"
859 * @return bool
861 function linkPrefixExtension() { return false; }
864 function &getMagicWords() {
865 global $wgMagicWordsEn;
866 return $wgMagicWordsEn;
869 # Fill a MagicWord object with data from here
870 function getMagic( &$mw ) {
871 $raw = $this->getMagicWords();
873 wfRunHooks( 'LanguageGetMagic', array( &$raw ) );
875 if( !isset( $raw[$mw->mId] ) ) {
876 # Fall back to English if local list is incomplete
877 $raw =& Language::getMagicWords();
879 $rawEntry = $raw[$mw->mId];
880 $mw->mCaseSensitive = $rawEntry[0];
881 $mw->mSynonyms = array_slice( $rawEntry, 1 );
885 * Italic is unsuitable for some languages
887 * @public
889 * @param string $text The text to be emphasized.
890 * @return string
892 function emphasize( $text ) {
893 return "<em>$text</em>";
897 * Normally we output all numbers in plain en_US style, that is
898 * 293,291.235 for twohundredninetythreethousand-twohundredninetyone
899 * point twohundredthirtyfive. However this is not sutable for all
900 * languages, some such as Pakaran want ੨੯੩,੨੯੫.੨੩੫ and others such as
901 * Icelandic just want to use commas instead of dots, and dots instead
902 * of commas like "293.291,235".
904 * An example of this function being called:
905 * <code>
906 * wfMsg( 'message', $wgLang->formatNum( $num ) )
907 * </code>
909 * See LanguageGu.php for the Gujarati implementation and
910 * LanguageIs.php for the , => . and . => , implementation.
912 * @todo check if it's viable to use localeconv() for the decimal
913 * seperator thing.
914 * @public
915 * @param mixed $number the string to be formatted, should be an integer or
916 * a floating point number.
917 * @param bool $nocommafy Set to true for special numbers like dates
918 * @return string
920 function formatNum( $number, $nocommafy = false ) {
921 global $wgTranslateNumerals;
922 if (!$nocommafy) {
923 $number = $this->commafy($number);
924 $s = $this->separatorTransformTable();
925 if (!is_null($s)) { $number = strtr($number, $s); }
928 if ($wgTranslateNumerals) {
929 $s = $this->digitTransformTable();
930 if (!is_null($s)) { $number = strtr($number, $s); }
933 return $number;
937 * Adds commas to a given number
939 * @param mixed $_
940 * @return string
942 function commafy($_) {
943 return strrev((string)preg_replace('/(\d{3})(?=\d)(?!\d*\.)/','$1,',strrev($_)));
946 function digitTransformTable() {
947 return null;
950 function separatorTransformTable() {
951 return null;
956 * For the credit list in includes/Credits.php (action=credits)
958 * @param array $l
959 * @return string
961 function listToText( $l ) {
962 $s = '';
963 $m = count($l) - 1;
964 for ($i = $m; $i >= 0; $i--) {
965 if ($i == $m) {
966 $s = $l[$i];
967 } else if ($i == $m - 1) {
968 $s = $l[$i] . ' ' . wfMsg('and') . ' ' . $s;
969 } else {
970 $s = $l[$i] . ', ' . $s;
973 return $s;
976 # Crop a string from the beginning or end to a certain number of bytes.
977 # (Bytes are used because our storage has limited byte lengths for some
978 # columns in the database.) Multibyte charsets will need to make sure that
979 # only whole characters are included!
981 # $length does not include the optional ellipsis.
982 # If $length is negative, snip from the beginning
983 function truncate( $string, $length, $ellipsis = '' ) {
984 if( $length == 0 ) {
985 return $ellipsis;
987 if ( strlen( $string ) <= abs( $length ) ) {
988 return $string;
990 if( $length > 0 ) {
991 $string = substr( $string, 0, $length );
992 return $string . $ellipsis;
993 } else {
994 $string = substr( $string, $length );
995 return $ellipsis . $string;
1000 * Grammatical transformations, needed for inflected languages
1001 * Invoked by putting {{grammar:case|word}} in a message
1003 * @param string $word
1004 * @param string $case
1005 * @return string
1007 function convertGrammar( $word, $case ) {
1008 global $wgGrammarForms;
1009 if ( isset($wgGrammarForms['en'][$case][$word]) ) {
1010 return $wgGrammarForms['en'][$case][$word];
1012 return $word;
1016 * Plural form transformations, needed for some languages.
1017 * For example, where are 3 form of plural in Russian and Polish,
1018 * depending on "count mod 10". See [[w:Plural]]
1019 * For English it is pretty simple.
1021 * Invoked by putting {{plural:count|wordform1|wordform2}}
1022 * or {{plural:count|wordform1|wordform2|wordform3}}
1024 * Example: {{plural:{{NUMBEROFARTICLES}}|article|articles}}
1026 * @param integer $count
1027 * @param string $wordform1
1028 * @param string $wordform2
1029 * @param string $wordform3 (optional)
1030 * @return string
1032 function convertPlural( $count, $wordform1, $wordform2, $wordform3) {
1033 return $count == '1' ? $wordform1 : $wordform2;
1037 * For translaing of expiry times
1038 * @param string The validated block time in English
1039 * @return Somehow translated block time
1040 * @see LanguageFi.php for example implementation
1042 function translateBlockExpiry( $str ) {
1044 $scBlockExpiryOptions = wfMsg( 'ipboptions' );
1046 if ( $scBlockExpiryOptions == '-') {
1047 return $str;
1050 foreach (explode(',', $scBlockExpiryOptions) as $option) {
1051 if ( strpos($option, ":") === false )
1052 continue;
1053 list($show, $value) = explode(":", $option);
1054 if ( strcmp ( $str, $value) == 0 )
1055 return '<span title="' . htmlspecialchars($str). '">' .
1056 htmlspecialchars( trim( $show ) ) . '</span>';
1059 return $str;
1063 * languages like Chinese need to be segmented in order for the diff
1064 * to be of any use
1066 * @param string $text
1067 * @return string
1069 function segmentForDiff( $text ) {
1070 return $text;
1074 * and unsegment to show the result
1076 * @param string $text
1077 * @return string
1079 function unsegmentForDiff( $text ) {
1080 return $text;
1083 # convert text to different variants of a language.
1084 function convert( $text, $isTitle = false) {
1085 return $this->mConverter->convert($text, $isTitle);
1088 # Convert text from within Parser
1089 function parserConvert( $text, &$parser ) {
1090 return $this->mConverter->parserConvert( $text, $parser );
1094 * Perform output conversion on a string, and encode for safe HTML output.
1095 * @param string $text
1096 * @param bool $isTitle -- wtf?
1097 * @return string
1098 * @todo this should get integrated somewhere sane
1100 function convertHtml( $text, $isTitle = false ) {
1101 return htmlspecialchars( $this->convert( $text, $isTitle ) );
1104 function convertCategoryKey( $key ) {
1105 return $this->mConverter->convertCategoryKey( $key );
1109 * get the list of variants supported by this langauge
1110 * see sample implementation in LanguageZh.php
1112 * @return array an array of language codes
1114 function getVariants() {
1115 return $this->mConverter->getVariants();
1119 function getPreferredVariant() {
1120 return $this->mConverter->getPreferredVariant();
1124 * if a language supports multiple variants, it is
1125 * possible that non-existing link in one variant
1126 * actually exists in another variant. this function
1127 * tries to find it. See e.g. LanguageZh.php
1129 * @param string $link the name of the link
1130 * @param mixed $nt the title object of the link
1131 * @return null the input parameters may be modified upon return
1133 function findVariantLink( &$link, &$nt ) {
1134 $this->mConverter->findVariantLink($link, $nt);
1138 * returns language specific options used by User::getPageRenderHash()
1139 * for example, the preferred language variant
1141 * @return string
1142 * @public
1144 function getExtraHashOptions() {
1145 return $this->mConverter->getExtraHashOptions();
1149 * for languages that support multiple variants, the title of an
1150 * article may be displayed differently in different variants. this
1151 * function returns the apporiate title defined in the body of the article.
1153 * @return string
1155 function getParsedTitle() {
1156 return $this->mConverter->getParsedTitle();
1160 * Enclose a string with the "no conversion" tag. This is used by
1161 * various functions in the Parser
1163 * @param string $text text to be tagged for no conversion
1164 * @return string the tagged text
1166 function markNoConversion( $text ) {
1167 return $this->mConverter->markNoConversion( $text );
1171 * A regular expression to match legal word-trailing characters
1172 * which should be merged onto a link of the form [[foo]]bar.
1174 * @return string
1175 * @public
1177 function linkTrail() {
1178 return $this->getMessage( 'linktrail' );
1181 function getLangObj() {
1182 return $this;
1186 * Get the RFC 3066 code for this language object
1188 function getCode() {
1189 return str_replace( '_', '-', strtolower( substr( get_class( $this ), 8 ) ) );
1195 # FIXME: Merge all UTF-8 support code into Language base class.
1196 # We no longer support Latin-1 charset.
1197 require_once( 'LanguageUtf8.php' );
1199 # This should fail gracefully if there's not a localization available
1200 wfSuppressWarnings();
1201 // Preload base classes to work around APC/PHP5 bug
1202 include_once( 'Language' . str_replace( '-', '_', ucfirst( $wgLanguageCode ) ) . '.deps.php' );
1203 include_once( 'Language' . str_replace( '-', '_', ucfirst( $wgLanguageCode ) ) . '.php' );
1204 wfRestoreWarnings();