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