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