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