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