* Introduce NUMBEROFPAGES magic word
[lhc/web/wiklou.git] / languages / Language.php
1 <?php
2 /**
3 * @package MediaWiki
4 * @subpackage Language
5 */
6
7 if( defined( 'MEDIAWIKI' ) ) {
8
9 #
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
14 #
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.
19 #
20
21 #--------------------------------------------------------------------------
22 # Language-specific text
23 #--------------------------------------------------------------------------
24
25 if($wgMetaNamespace === FALSE)
26 $wgMetaNamespace = str_replace( ' ', '_', $wgSitename );
27
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',
47 );
48
49 if(isset($wgExtraNamespaces)) {
50 $wgNamespaceNamesEn=$wgNamespaceNamesEn+$wgExtraNamespaces;
51 }
52
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,
89 );
90
91 /* private */ $wgQuickbarSettingsEn = array(
92 'None', 'Fixed left', 'Fixed right', 'Floating left', 'Floating right'
93 );
94
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'
104 );
105
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'
113 );
114
115 /**
116 * Whether to use user or default setting in Language::date()
117 *
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.
121 *
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().
124 *
125 * @private
126 */
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'
133 );
134
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',
169 );
170
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'
176 );
177
178 # Read language names
179 global $wgLanguageNames;
180 /** */
181 require_once( 'Names.php' );
182
183 $wgLanguageNamesEn =& $wgLanguageNames;
184
185
186 /* private */ $wgWeekdayNamesEn = array(
187 'sunday', 'monday', 'tuesday', 'wednesday', 'thursday',
188 'friday', 'saturday'
189 );
190
191
192 /* private */ $wgMonthNamesEn = array(
193 'january', 'february', 'march', 'april', 'may_long', 'june',
194 'july', 'august', 'september', 'october', 'november',
195 'december'
196 );
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'
201 );
202
203 /* private */ $wgMonthAbbreviationsEn = array(
204 'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug',
205 'sep', 'oct', 'nov', 'dec'
206 );
207
208 # Note to translators:
209 # Please include the English words as synonyms. This allows people
210 # from other wikis to contribute more easily.
211 #
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_TALKPAGENAME => array( 1, 'TALKPAGENAME' ),
246 MAG_TALKPAGENAMEE => array( 1, 'TALKPAGENAMEE' ),
247 MAG_SUBJECTPAGENAME => array( 1, 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ),
248 MAG_SUBJECTPAGENAMEE => array( 1, 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ),
249 MAG_MSG => array( 0, 'MSG:' ),
250 MAG_SUBST => array( 0, 'SUBST:' ),
251 MAG_MSGNW => array( 0, 'MSGNW:' ),
252 MAG_END => array( 0, '__END__' ),
253 MAG_IMG_THUMBNAIL => array( 1, 'thumbnail', 'thumb' ),
254 MAG_IMG_MANUALTHUMB => array( 1, 'thumbnail=$1', 'thumb=$1'),
255 MAG_IMG_RIGHT => array( 1, 'right' ),
256 MAG_IMG_LEFT => array( 1, 'left' ),
257 MAG_IMG_NONE => array( 1, 'none' ),
258 MAG_IMG_WIDTH => array( 1, '$1px' ),
259 MAG_IMG_CENTER => array( 1, 'center', 'centre' ),
260 MAG_IMG_FRAMED => array( 1, 'framed', 'enframed', 'frame' ),
261 MAG_INT => array( 0, 'INT:' ),
262 MAG_SITENAME => array( 1, 'SITENAME' ),
263 MAG_NS => array( 0, 'NS:' ),
264 MAG_LOCALURL => array( 0, 'LOCALURL:' ),
265 MAG_LOCALURLE => array( 0, 'LOCALURLE:' ),
266 MAG_SERVER => array( 0, 'SERVER' ),
267 MAG_SERVERNAME => array( 0, 'SERVERNAME' ),
268 MAG_SCRIPTPATH => array( 0, 'SCRIPTPATH' ),
269 MAG_GRAMMAR => array( 0, 'GRAMMAR:' ),
270 MAG_NOTITLECONVERT => array( 0, '__NOTITLECONVERT__', '__NOTC__'),
271 MAG_NOCONTENTCONVERT => array( 0, '__NOCONTENTCONVERT__', '__NOCC__'),
272 MAG_CURRENTWEEK => array( 1, 'CURRENTWEEK' ),
273 MAG_CURRENTDOW => array( 1, 'CURRENTDOW' ),
274 MAG_REVISIONID => array( 1, 'REVISIONID' ),
275 MAG_PLURAL => array( 0, 'PLURAL:' ),
276 MAG_FULLURL => array( 0, 'FULLURL:' ),
277 MAG_FULLURLE => array( 0, 'FULLURLE:' ),
278 MAG_LCFIRST => array( 0, 'LCFIRST:' ),
279 MAG_UCFIRST => array( 0, 'UCFIRST:' ),
280 MAG_LC => array( 0, 'LC:' ),
281 MAG_UC => array( 0, 'UC:' ),
282 MAG_RAW => array( 0, 'RAW:' ),
283 MAG_DISPLAYTITLE => array( 1, 'DISPLAYTITLE' ),
284 MAG_RAWSUFFIX => array( 1, 'R' ),
285 MAG_NEWSECTIONLINK => array( 1, '__NEWSECTIONLINK__' ),
286 MAG_CURRENTVERSION => array( 1, 'CURRENTVERSION' ),
287 );
288
289 if (!$wgCachedMessageArrays) {
290 require_once('Messages.php');
291 }
292
293 /* a fake language converter */
294 class fakeConverter {
295 var $mLang;
296 function fakeConverter($langobj) {$this->mLang = $langobj;}
297 function convert($t, $i) {return $t;}
298 function parserConvert($t, $p) {return $t;}
299 function getVariants() { return array( $this->mLang->getCode() ); }
300 function getPreferredVariant() {return $this->mLang->getCode(); }
301 function findVariantLink(&$l, &$n) {}
302 function getExtraHashOptions() {return '';}
303 function getParsedTitle() {return '';}
304 function markNoConversion($text) {return $text;}
305 function convertCategoryKey( $key ) {return $key; }
306
307 }
308
309 #--------------------------------------------------------------------------
310 # Internationalisation code
311 #--------------------------------------------------------------------------
312
313 class Language {
314 var $mConverter;
315 function Language() {
316
317 # Copies any missing values in the specified arrays from En to the current language
318 $fillin = array( 'wgSysopSpecialPages', 'wgValidSpecialPages', 'wgDeveloperSpecialPages' );
319 $name = get_class( $this );
320
321 if( strpos( $name, 'language' ) == 0){
322 $lang = ucfirst( substr( $name, 8 ) );
323 foreach( $fillin as $arrname ){
324 $langver = "{$arrname}{$lang}";
325 $enver = "{$arrname}En";
326 if( ! isset( $GLOBALS[$langver] ) || ! isset( $GLOBALS[$enver] ))
327 continue;
328 foreach($GLOBALS[$enver] as $spage => $text){
329 if( ! isset( $GLOBALS[$langver][$spage] ) )
330 $GLOBALS[$langver][$spage] = $text;
331 }
332 }
333 }
334 $this->mConverter = new fakeConverter($this);
335 }
336
337 /**
338 * Exports the default user options as defined in
339 * $wgDefaultUserOptionsEn, user preferences can override some of these
340 * depending on what's in (Local|Default)Settings.php and some defines.
341 *
342 * @return array
343 */
344 function getDefaultUserOptions() {
345 global $wgDefaultUserOptionsEn ;
346 return $wgDefaultUserOptionsEn ;
347 }
348
349 /**
350 * Exports $wgBookstoreListEn
351 * @return array
352 */
353 function getBookstoreList() {
354 global $wgBookstoreListEn ;
355 return $wgBookstoreListEn ;
356 }
357
358 /**
359 * @return array
360 */
361 function getNamespaces() {
362 global $wgNamespaceNamesEn;
363 return $wgNamespaceNamesEn;
364 }
365
366 /**
367 * A convenience function that returns the same thing as
368 * getNamespaces() except with the array values changed to ' '
369 * where it found '_', useful for producing output to be displayed
370 * e.g. in <select> forms.
371 *
372 * @return array
373 */
374 function getFormattedNamespaces() {
375 $ns = $this->getNamespaces();
376 foreach($ns as $k => $v) {
377 $ns[$k] = strtr($v, '_', ' ');
378 }
379 return $ns;
380 }
381
382 /**
383 * Get a namespace value by key
384 * <code>
385 * $mw_ns = $wgContLang->getNsText( NS_MEDIAWIKI );
386 * echo $mw_ns; // prints 'MediaWiki'
387 * </code>
388 *
389 * @param int $index the array key of the namespace to return
390 * @return mixed, string if the namespace value exists, otherwise false
391 */
392 function getNsText( $index ) {
393 $ns = $this->getNamespaces();
394 return isset( $ns[$index] ) ? $ns[$index] : false;
395 }
396
397 /**
398 * A convenience function that returns the same thing as
399 * getNsText() except with '_' changed to ' ', useful for
400 * producing output.
401 *
402 * @return array
403 */
404 function getFormattedNsText( $index ) {
405 $ns = $this->getNsText( $index );
406 return strtr($ns, '_', ' ');
407 }
408
409 /**
410 * Get a namespace key by value, case insensetive.
411 *
412 * @param string $text
413 * @return mixed An integer if $text is a valid value otherwise false
414 */
415 function getNsIndex( $text ) {
416 $ns = $this->getNamespaces();
417
418 foreach ( $ns as $i => $n ) {
419 if ( strcasecmp( $n, $text ) == 0)
420 return $i;
421 }
422 return false;
423 }
424
425 /**
426 * short names for language variants used for language conversion links.
427 *
428 * @param string $code
429 * @return string
430 */
431 function getVariantname( $code ) {
432 return wfMsg( "variantname-$code" );
433 }
434
435 function specialPage( $name ) {
436 return $this->getNsText(NS_SPECIAL) . ':' . $name;
437 }
438
439 function getQuickbarSettings() {
440 global $wgQuickbarSettingsEn;
441 return $wgQuickbarSettingsEn;
442 }
443
444 function getSkinNames() {
445 global $wgSkinNamesEn;
446 return $wgSkinNamesEn;
447 }
448
449 function getMathNames() {
450 global $wgMathNamesEn;
451 return $wgMathNamesEn;
452 }
453
454 function getDateFormats() {
455 global $wgDateFormatsEn;
456 return $wgDateFormatsEn;
457 }
458
459 function getUserToggles() {
460 global $wgUserTogglesEn;
461 return $wgUserTogglesEn;
462 }
463
464 function getUserToggle( $tog ) {
465 return wfMsg( "tog-$tog" );
466 }
467
468 function getLanguageNames() {
469 global $wgLanguageNamesEn;
470 return $wgLanguageNamesEn;
471 }
472
473 function getLanguageName( $code ) {
474 global $wgLanguageNamesEn;
475 if ( ! array_key_exists( $code, $wgLanguageNamesEn ) ) {
476 return '';
477 }
478 return $wgLanguageNamesEn[$code];
479 }
480
481 function getMonthName( $key ) {
482 global $wgMonthNamesEn, $wgContLang;
483 // see who called us and use the correct message function
484 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
485 return wfMsgForContent($wgMonthNamesEn[$key-1]);
486 else
487 return wfMsg($wgMonthNamesEn[$key-1]);
488 }
489
490 /* by default we just return base form */
491 function getMonthNameGen( $key ) {
492 return $this->getMonthName( $key );
493 }
494
495 function getMonthAbbreviation( $key ) {
496 global $wgMonthAbbreviationsEn, $wgContLang;
497 // see who called us and use the correct message function
498 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
499 return wfMsgForContent(@$wgMonthAbbreviationsEn[$key-1]);
500 else
501 return wfMsg(@$wgMonthAbbreviationsEn[$key-1]);
502 }
503
504 function getWeekdayName( $key ) {
505 global $wgWeekdayNamesEn, $wgContLang;
506 // see who called us and use the correct message function
507 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
508 return wfMsgForContent($wgWeekdayNamesEn[$key-1]);
509 else
510 return wfMsg($wgWeekdayNamesEn[$key-1]);
511 }
512
513 /**
514 * Used by date() and time() to adjust the time output.
515 * @public
516 * @param int $ts the time in date('YmdHis') format
517 * @param mixed $tz adjust the time by this amount (default false,
518 * mean we get user timecorrection setting)
519 * @return int
520
521 */
522 function userAdjust( $ts, $tz = false ) {
523 global $wgUser, $wgLocalTZoffset;
524
525 if (!$tz) {
526 $tz = $wgUser->getOption( 'timecorrection' );
527 }
528
529 # minutes and hours differences:
530 $minDiff = 0;
531 $hrDiff = 0;
532
533 if ( $tz === '' ) {
534 # Global offset in minutes.
535 if( isset($wgLocalTZoffset) ) {
536 $hrDiff = $wgLocalTZoffset % 60;
537 $minDiff = $wgLocalTZoffset - ($hrDiff * 60);
538 }
539 } elseif ( strpos( $tz, ':' ) !== false ) {
540 $tzArray = explode( ':', $tz );
541 $hrDiff = intval($tzArray[0]);
542 $minDiff = intval($hrDiff < 0 ? -$tzArray[1] : $tzArray[1]);
543 } else {
544 $hrDiff = intval( $tz );
545 }
546
547 # No difference ? Return time unchanged
548 if ( 0 == $hrDiff && 0 == $minDiff ) { return $ts; }
549
550 # Generate an adjusted date
551 $t = mktime( (
552 (int)substr( $ts, 8, 2) ) + $hrDiff, # Hours
553 (int)substr( $ts, 10, 2 ) + $minDiff, # Minutes
554 (int)substr( $ts, 12, 2 ), # Seconds
555 (int)substr( $ts, 4, 2 ), # Month
556 (int)substr( $ts, 6, 2 ), # Day
557 (int)substr( $ts, 0, 4 ) ); #Year
558 return date( 'YmdHis', $t );
559 }
560
561 /**
562 * This is meant to be used by time(), date(), and timeanddate() to get
563 * the date preference they're supposed to use, it should be used in
564 * all children.
565 *
566 *<code>
567 * function timeanddate([...], $format = true) {
568 * $datePreference = $this->dateFormat($format);
569 * [...]
570 *</code>
571 *
572 * @param mixed $usePrefs: if true, the user's preference is used
573 * if false, the site/language default is used
574 * if int/string, assumed to be a format.
575 * @return string
576 */
577 function dateFormat( $usePrefs = true ) {
578 global $wgUser;
579
580 if( is_bool( $usePrefs ) ) {
581 if( $usePrefs ) {
582 $datePreference = $wgUser->getOption( 'date' );
583 } else {
584 $options = $this->getDefaultUserOptions();
585 $datePreference = (string)$options['date'];
586 }
587 } else {
588 $datePreference = (string)$usePrefs;
589 }
590
591 // return int
592 if( $datePreference == '' ) {
593 return MW_DATE_DEFAULT;
594 }
595
596 return $datePreference;
597 }
598
599 /**
600 * @public
601 * @param mixed $ts the time format which needs to be turned into a
602 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
603 * @param bool $adj whether to adjust the time output according to the
604 * user configured offset ($timecorrection)
605 * @param mixed $format true to use user's date format preference
606 * @param string $timecorrection the time offset as returned by
607 * validateTimeZone() in Special:Preferences
608 * @return string
609 */
610 function date( $ts, $adj = false, $format = true, $timecorrection = false ) {
611 global $wgUser, $wgAmericanDates;
612
613 if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
614
615 $datePreference = $this->dateFormat( $format );
616 if( $datePreference == MW_DATE_DEFAULT ) {
617 $datePreference = $wgAmericanDates ? MW_DATE_MDY : MW_DATE_DMY;
618 }
619
620 $month = $this->formatMonth( substr( $ts, 4, 2 ), $datePreference );
621 $day = $this->formatDay( substr( $ts, 6, 2 ), $datePreference );
622 $year = $this->formatNum( substr( $ts, 0, 4 ), true );
623
624 switch( $datePreference ) {
625 case MW_DATE_DMY: return "$day $month $year";
626 case MW_DATE_YMD: return "$year $month $day";
627 case MW_DATE_ISO: return substr($ts, 0, 4). '-' . substr($ts, 4, 2). '-' .substr($ts, 6, 2);
628 default: return "$month $day, $year";
629 }
630 }
631
632 /**
633 * @public
634 * @param mixed $ts the time format which needs to be turned into a
635 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
636 * @param bool $adj whether to adjust the time output according to the
637 * user configured offset ($timecorrection)
638 * @param mixed $format true to use user's date format preference
639 * @param string $timecorrection the time offset as returned by
640 * validateTimeZone() in Special:Preferences
641 * @return string
642 */
643 function time( $ts, $adj = false, $format = true, $timecorrection = false ) {
644 global $wgUser;
645
646 if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
647 $datePreference = $this->dateFormat( $format );
648
649 $sep = $this->timeSeparator( $format );
650
651 $hh = substr( $ts, 8, 2 );
652 $mm = substr( $ts, 10, 2 );
653 $ss = substr( $ts, 12, 2 );
654
655 if ( $datePreference != MW_DATE_ISO ) {
656 $hh = $this->formatNum( $hh, true );
657 $mm = $this->formatNum( $mm, true );
658 //$ss = $this->formatNum( $ss, true );
659 return $hh . $sep . $mm;
660 } else {
661 return $hh . ':' . $mm . ':' . $ss;
662 }
663 }
664
665 /**
666 * Default separator character between hours, minutes, and seconds.
667 * Will be used by Language::time() for non-ISO formats.
668 * (ISO will always use a colon.)
669 * @return string
670 */
671 function timeSeparator( $format ) {
672 return ':';
673 }
674
675 /**
676 * String to insert between the time and the date in a combined
677 * string. Should include any relevant whitespace.
678 * @return string
679 */
680 function timeDateSeparator( $format ) {
681 return ', ';
682 }
683
684 /**
685 * Return true if the time should display before the date.
686 * @return bool
687 * @private
688 */
689 function timeBeforeDate() {
690 return true;
691 }
692
693 function formatMonth( $month, $format ) {
694 return $this->getMonthName( $month );
695 }
696
697 function formatDay( $day, $format ) {
698 return $this->formatNum( 0 + $day, true );
699 }
700
701 /**
702 * @public
703 * @param mixed $ts the time format which needs to be turned into a
704 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
705 * @param bool $adj whether to adjust the time output according to the
706 * user configured offset ($timecorrection)
707
708 * @param mixed $format what format to return, if it's false output the
709 * default one (default true)
710 * @param string $timecorrection the time offset as returned by
711 * validateTimeZone() in Special:Preferences
712 * @return string
713 */
714 function timeanddate( $ts, $adj = false, $format = true, $timecorrection = false) {
715 global $wgUser;
716
717 $datePreference = $this->dateFormat($format);
718 switch ( $datePreference ) {
719 case MW_DATE_ISO: return $this->date( $ts, $adj, $format, $timecorrection ) . ' ' .
720 $this->time( $ts, $adj, $format, $timecorrection );
721 default:
722 $time = $this->time( $ts, $adj, $format, $timecorrection );
723 $sep = $this->timeDateSeparator( $datePreference );
724 $date = $this->date( $ts, $adj, $format, $timecorrection );
725 return $this->timeBeforeDate( $datePreference )
726 ? $time . $sep . $date
727 : $date . $sep . $time;
728 }
729 }
730
731 function getMessage( $key ) {
732 global $wgAllMessagesEn;
733 return @$wgAllMessagesEn[$key];
734 }
735
736 function getAllMessages() {
737 global $wgAllMessagesEn;
738 return $wgAllMessagesEn;
739 }
740
741 function iconv( $in, $out, $string ) {
742 # For most languages, this is a wrapper for iconv
743 return iconv( $in, $out, $string );
744 }
745
746 function ucfirst( $string ) {
747 # For most languages, this is a wrapper for ucfirst()
748 return ucfirst( $string );
749 }
750
751 function uc( $str ) {
752 return strtoupper( $str );
753 }
754
755 function lcfirst( $s ) {
756 return strtolower( $s{0} ). substr( $s, 1 );
757 }
758
759 function lc( $str ) {
760 return strtolower( $str );
761 }
762
763 function checkTitleEncoding( $s ) {
764 global $wgInputEncoding;
765
766 # Check for UTF-8 URLs; Internet Explorer produces these if you
767 # type non-ASCII chars in the URL bar or follow unescaped links.
768 $ishigh = preg_match( '/[\x80-\xff]/', $s);
769 $isutf = ($ishigh ? preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
770 '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s ) : true );
771
772 if( ($wgInputEncoding != 'utf-8') and $ishigh and $isutf )
773 return @iconv( 'UTF-8', $wgInputEncoding, $s );
774
775 if( ($wgInputEncoding == 'utf-8') and $ishigh and !$isutf )
776 return utf8_encode( $s );
777
778 # Other languages can safely leave this function, or replace
779 # it with one to detect and convert another legacy encoding.
780 return $s;
781 }
782
783 /**
784 * Some languages have special punctuation to strip out
785 * or characters which need to be converted for MySQL's
786 * indexing to grok it correctly. Make such changes here.
787 *
788 * @param string $in
789 * @return string
790 */
791 function stripForSearch( $in ) {
792 return strtolower( $in );
793 }
794
795 function convertForSearchResult( $termsArray ) {
796 # some languages, e.g. Chinese, need to do a conversion
797 # in order for search results to be displayed correctly
798 return $termsArray;
799 }
800
801 /**
802 * Get the first character of a string. In ASCII, return
803 * first byte of the string. UTF8 and others have to
804 * overload this.
805 *
806 * @param string $s
807 * @return string
808 */
809 function firstChar( $s ) {
810 return $s[0];
811 }
812
813 function initEncoding() {
814 # Some languages may have an alternate char encoding option
815 # (Esperanto X-coding, Japanese furigana conversion, etc)
816 # If this language is used as the primary content language,
817 # an override to the defaults can be set here on startup.
818 #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
819 }
820
821 function setAltEncoding() {
822 # Some languages may have an alternate char encoding option
823 # (Esperanto X-coding, Japanese furigana conversion, etc)
824 # If 'altencoding' is checked in user prefs, this gives a
825 # chance to swap out the default encoding settings.
826 #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
827 }
828
829 function recodeForEdit( $s ) {
830 # For some languages we'll want to explicitly specify
831 # which characters make it into the edit box raw
832 # or are converted in some way or another.
833 # Note that if wgOutputEncoding is different from
834 # wgInputEncoding, this text will be further converted
835 # to wgOutputEncoding.
836 global $wgInputEncoding, $wgEditEncoding;
837 if( $wgEditEncoding == '' or
838 $wgEditEncoding == $wgInputEncoding ) {
839 return $s;
840 } else {
841 return $this->iconv( $wgInputEncoding, $wgEditEncoding, $s );
842 }
843 }
844
845 function recodeInput( $s ) {
846 # Take the previous into account.
847 global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
848 if($wgEditEncoding != "") {
849 $enc = $wgEditEncoding;
850 } else {
851 $enc = $wgOutputEncoding;
852 }
853 if( $enc == $wgInputEncoding ) {
854 return $s;
855 } else {
856 return $this->iconv( $enc, $wgInputEncoding, $s );
857 }
858 }
859
860 /**
861 * For right-to-left language support
862 *
863 * @return bool
864 */
865 function isRTL() { return false; }
866 function getDirMark() { return $this->isRTL() ? '&rlm;' : '&lrm;'; }
867
868 /**
869 * To allow "foo[[bar]]" to extend the link over the whole word "foobar"
870 *
871 * @return bool
872 */
873 function linkPrefixExtension() { return false; }
874
875
876 function &getMagicWords() {
877 global $wgMagicWordsEn;
878 return $wgMagicWordsEn;
879 }
880
881 # Fill a MagicWord object with data from here
882 function getMagic( &$mw ) {
883 $raw = $this->getMagicWords();
884
885 wfRunHooks( 'LanguageGetMagic', array( &$raw ) );
886
887 if( !isset( $raw[$mw->mId] ) ) {
888 # Fall back to English if local list is incomplete
889 $raw =& Language::getMagicWords();
890 }
891 $rawEntry = $raw[$mw->mId];
892 $mw->mCaseSensitive = $rawEntry[0];
893 $mw->mSynonyms = array_slice( $rawEntry, 1 );
894 }
895
896 /**
897 * Italic is unsuitable for some languages
898 *
899 * @public
900 *
901 * @param string $text The text to be emphasized.
902 * @return string
903 */
904 function emphasize( $text ) {
905 return "<em>$text</em>";
906 }
907
908 /**
909 * Normally we output all numbers in plain en_US style, that is
910 * 293,291.235 for twohundredninetythreethousand-twohundredninetyone
911 * point twohundredthirtyfive. However this is not sutable for all
912 * languages, some such as Pakaran want ੨੯੩,੨੯੫.੨੩੫ and others such as
913 * Icelandic just want to use commas instead of dots, and dots instead
914 * of commas like "293.291,235".
915 *
916 * An example of this function being called:
917 * <code>
918 * wfMsg( 'message', $wgLang->formatNum( $num ) )
919 * </code>
920 *
921 * See LanguageGu.php for the Gujarati implementation and
922 * LanguageIs.php for the , => . and . => , implementation.
923 *
924 * @todo check if it's viable to use localeconv() for the decimal
925 * seperator thing.
926 * @public
927 * @param mixed $number the string to be formatted, should be an integer or
928 * a floating point number.
929 * @param bool $nocommafy Set to true for special numbers like dates
930 * @return string
931 */
932 function formatNum( $number, $nocommafy = false ) {
933 global $wgTranslateNumerals;
934 if (!$nocommafy) {
935 $number = $this->commafy($number);
936 $s = $this->separatorTransformTable();
937 if (!is_null($s)) { $number = strtr($number, $s); }
938 }
939
940 if ($wgTranslateNumerals) {
941 $s = $this->digitTransformTable();
942 if (!is_null($s)) { $number = strtr($number, $s); }
943 }
944
945 return $number;
946 }
947
948 /**
949 * Adds commas to a given number
950 *
951 * @param mixed $_
952 * @return string
953 */
954 function commafy($_) {
955 return strrev((string)preg_replace('/(\d{3})(?=\d)(?!\d*\.)/','$1,',strrev($_)));
956 }
957
958 function digitTransformTable() {
959 return null;
960 }
961
962 function separatorTransformTable() {
963 return null;
964 }
965
966
967 /**
968 * For the credit list in includes/Credits.php (action=credits)
969 *
970 * @param array $l
971 * @return string
972 */
973 function listToText( $l ) {
974 $s = '';
975 $m = count($l) - 1;
976 for ($i = $m; $i >= 0; $i--) {
977 if ($i == $m) {
978 $s = $l[$i];
979 } else if ($i == $m - 1) {
980 $s = $l[$i] . ' ' . wfMsg('and') . ' ' . $s;
981 } else {
982 $s = $l[$i] . ', ' . $s;
983 }
984 }
985 return $s;
986 }
987
988 # Crop a string from the beginning or end to a certain number of bytes.
989 # (Bytes are used because our storage has limited byte lengths for some
990 # columns in the database.) Multibyte charsets will need to make sure that
991 # only whole characters are included!
992 #
993 # $length does not include the optional ellipsis.
994 # If $length is negative, snip from the beginning
995 function truncate( $string, $length, $ellipsis = '' ) {
996 if( $length == 0 ) {
997 return $ellipsis;
998 }
999 if ( strlen( $string ) <= abs( $length ) ) {
1000 return $string;
1001 }
1002 if( $length > 0 ) {
1003 $string = substr( $string, 0, $length );
1004 return $string . $ellipsis;
1005 } else {
1006 $string = substr( $string, $length );
1007 return $ellipsis . $string;
1008 }
1009 }
1010
1011 /**
1012 * Grammatical transformations, needed for inflected languages
1013 * Invoked by putting {{grammar:case|word}} in a message
1014 *
1015 * @param string $word
1016 * @param string $case
1017 * @return string
1018 */
1019 function convertGrammar( $word, $case ) {
1020 return $word;
1021 }
1022
1023 /**
1024 * Plural form transformations, needed for some languages.
1025 * For example, where are 3 form of plural in Russian and Polish,
1026 * depending on "count mod 10". See [[w:Plural]]
1027 * For English it is pretty simple.
1028 *
1029 * Invoked by putting {{plural:count|wordform1|wordform2}}
1030 * or {{plural:count|wordform1|wordform2|wordform3}}
1031 *
1032 * Example: {{plural:{{NUMBEROFARTICLES}}|article|articles}}
1033 *
1034 * @param integer $count
1035 * @param string $wordform1
1036 * @param string $wordform2
1037 * @param string $wordform3 (optional)
1038 * @return string
1039 */
1040 function convertPlural( $count, $wordform1, $wordform2, $wordform3) {
1041 return $count == '1' ? $wordform1 : $wordform2;
1042 }
1043
1044 /**
1045 * For translaing of expiry times
1046 * @param string The validated block time in English
1047 * @return Somehow translated block time
1048 * @see LanguageFi.php for example implementation
1049 */
1050 function translateBlockExpiry( $str ) {
1051
1052 $scBlockExpiryOptions = wfMsg( 'ipboptions' );
1053
1054 if ( $scBlockExpiryOptions == '-') {
1055 return $str;
1056 }
1057
1058 foreach (explode(',', $scBlockExpiryOptions) as $option) {
1059 if ( strpos($option, ":") === false )
1060 continue;
1061 list($show, $value) = explode(":", $option);
1062 if ( strcmp ( $str, $value) == 0 )
1063 return '<span title="' . htmlspecialchars($str). '">' .
1064 htmlspecialchars( trim( $show ) ) . '</span>';
1065 }
1066
1067 return $str;
1068 }
1069
1070 /**
1071 * languages like Chinese need to be segmented in order for the diff
1072 * to be of any use
1073 *
1074 * @param string $text
1075 * @return string
1076 */
1077 function segmentForDiff( $text ) {
1078 return $text;
1079 }
1080
1081 /**
1082 * and unsegment to show the result
1083 *
1084 * @param string $text
1085 * @return string
1086 */
1087 function unsegmentForDiff( $text ) {
1088 return $text;
1089 }
1090
1091 # convert text to different variants of a language.
1092 function convert( $text, $isTitle = false) {
1093 return $this->mConverter->convert($text, $isTitle);
1094 }
1095
1096 # Convert text from within Parser
1097 function parserConvert( $text, &$parser ) {
1098 return $this->mConverter->parserConvert( $text, $parser );
1099 }
1100
1101 /**
1102 * Perform output conversion on a string, and encode for safe HTML output.
1103 * @param string $text
1104 * @param bool $isTitle -- wtf?
1105 * @return string
1106 * @todo this should get integrated somewhere sane
1107 */
1108 function convertHtml( $text, $isTitle = false ) {
1109 return htmlspecialchars( $this->convert( $text, $isTitle ) );
1110 }
1111
1112 function convertCategoryKey( $key ) {
1113 return $this->mConverter->convertCategoryKey( $key );
1114 }
1115
1116 /**
1117 * get the list of variants supported by this langauge
1118 * see sample implementation in LanguageZh.php
1119 *
1120 * @return array an array of language codes
1121 */
1122 function getVariants() {
1123 return $this->mConverter->getVariants();
1124 }
1125
1126
1127 function getPreferredVariant() {
1128 return $this->mConverter->getPreferredVariant();
1129 }
1130
1131 /**
1132 * if a language supports multiple variants, it is
1133 * possible that non-existing link in one variant
1134 * actually exists in another variant. this function
1135 * tries to find it. See e.g. LanguageZh.php
1136 *
1137 * @param string $link the name of the link
1138 * @param mixed $nt the title object of the link
1139 * @return null the input parameters may be modified upon return
1140 */
1141 function findVariantLink( &$link, &$nt ) {
1142 $this->mConverter->findVariantLink($link, $nt);
1143 }
1144
1145 /**
1146 * returns language specific options used by User::getPageRenderHash()
1147 * for example, the preferred language variant
1148 *
1149 * @return string
1150 * @public
1151 */
1152 function getExtraHashOptions() {
1153 return $this->mConverter->getExtraHashOptions();
1154 }
1155
1156 /**
1157 * for languages that support multiple variants, the title of an
1158 * article may be displayed differently in different variants. this
1159 * function returns the apporiate title defined in the body of the article.
1160 *
1161 * @return string
1162 */
1163 function getParsedTitle() {
1164 return $this->mConverter->getParsedTitle();
1165 }
1166
1167 /**
1168 * Enclose a string with the "no conversion" tag. This is used by
1169 * various functions in the Parser
1170 *
1171 * @param string $text text to be tagged for no conversion
1172 * @return string the tagged text
1173 */
1174 function markNoConversion( $text ) {
1175 return $this->mConverter->markNoConversion( $text );
1176 }
1177
1178 /**
1179 * A regular expression to match legal word-trailing characters
1180 * which should be merged onto a link of the form [[foo]]bar.
1181 *
1182 * @return string
1183 * @public
1184 */
1185 function linkTrail() {
1186 return $this->getMessage( 'linktrail' );
1187 }
1188
1189 function getLangObj() {
1190 return $this;
1191 }
1192
1193 /**
1194 * Get the RFC 3066 code for this language object
1195 */
1196 function getCode() {
1197 return str_replace( '_', '-', strtolower( substr( get_class( $this ), 8 ) ) );
1198 }
1199
1200
1201 }
1202
1203 # FIXME: Merge all UTF-8 support code into Language base class.
1204 # We no longer support Latin-1 charset.
1205 require_once( 'LanguageUtf8.php' );
1206
1207 # This should fail gracefully if there's not a localization available
1208 wfSuppressWarnings();
1209 // Preload base classes to work around APC/PHP5 bug
1210 include_once( 'Language' . str_replace( '-', '_', ucfirst( $wgLanguageCode ) ) . '.deps.php' );
1211 include_once( 'Language' . str_replace( '-', '_', ucfirst( $wgLanguageCode ) ) . '.php' );
1212 wfRestoreWarnings();
1213
1214 }
1215 ?>