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