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