(bug 6392) Fix misbehaving <br /> in preferences form
[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_NOGALLERY => array( 0, '__NOGALLERY__' ),
217 MAG_FORCETOC => array( 0, '__FORCETOC__' ),
218 MAG_TOC => array( 0, '__TOC__' ),
219 MAG_NOEDITSECTION => array( 0, '__NOEDITSECTION__' ),
220 MAG_START => array( 0, '__START__' ),
221 MAG_CURRENTMONTH => array( 1, 'CURRENTMONTH' ),
222 MAG_CURRENTMONTHNAME => array( 1, 'CURRENTMONTHNAME' ),
223 MAG_CURRENTMONTHNAMEGEN => array( 1, 'CURRENTMONTHNAMEGEN' ),
224 MAG_CURRENTMONTHABBREV => array( 1, 'CURRENTMONTHABBREV' ),
225 MAG_CURRENTDAY => array( 1, 'CURRENTDAY' ),
226 MAG_CURRENTDAY2 => array( 1, 'CURRENTDAY2' ),
227 MAG_CURRENTDAYNAME => array( 1, 'CURRENTDAYNAME' ),
228 MAG_CURRENTYEAR => array( 1, 'CURRENTYEAR' ),
229 MAG_CURRENTTIME => array( 1, 'CURRENTTIME' ),
230 MAG_NUMBEROFPAGES => array( 1, 'NUMBEROFPAGES' ),
231 MAG_NUMBEROFARTICLES => array( 1, 'NUMBEROFARTICLES' ),
232 MAG_NUMBEROFFILES => array( 1, 'NUMBEROFFILES' ),
233 MAG_NUMBEROFUSERS => array( 1, 'NUMBEROFUSERS' ),
234 MAG_PAGENAME => array( 1, 'PAGENAME' ),
235 MAG_PAGENAMEE => array( 1, 'PAGENAMEE' ),
236 MAG_NAMESPACE => array( 1, 'NAMESPACE' ),
237 MAG_NAMESPACEE => array( 1, 'NAMESPACEE' ),
238 MAG_TALKSPACE => array( 1, 'TALKSPACE' ),
239 MAG_TALKSPACEE => array( 1, 'TALKSPACEE' ),
240 MAG_SUBJECTSPACE => array( 1, 'SUBJECTSPACE', 'ARTICLESPACE' ),
241 MAG_SUBJECTSPACEE => array( 1, 'SUBJECTSPACEE', 'ARTICLESPACEE' ),
242 MAG_FULLPAGENAME => array( 1, 'FULLPAGENAME' ),
243 MAG_FULLPAGENAMEE => array( 1, 'FULLPAGENAMEE' ),
244 MAG_SUBPAGENAME => array( 1, 'SUBPAGENAME' ),
245 MAG_SUBPAGENAMEE => array( 1, 'SUBPAGENAMEE' ),
246 MAG_BASEPAGENAME => array( 1, 'BASEPAGENAME' ),
247 MAG_BASEPAGENAMEE => array( 1, 'BASEPAGENAMEE' ),
248 MAG_TALKPAGENAME => array( 1, 'TALKPAGENAME' ),
249 MAG_TALKPAGENAMEE => array( 1, 'TALKPAGENAMEE' ),
250 MAG_SUBJECTPAGENAME => array( 1, 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ),
251 MAG_SUBJECTPAGENAMEE => array( 1, 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ),
252 MAG_MSG => array( 0, 'MSG:' ),
253 MAG_SUBST => array( 0, 'SUBST:' ),
254 MAG_MSGNW => array( 0, 'MSGNW:' ),
255 MAG_END => array( 0, '__END__' ),
256 MAG_IMG_THUMBNAIL => array( 1, 'thumbnail', 'thumb' ),
257 MAG_IMG_MANUALTHUMB => array( 1, 'thumbnail=$1', 'thumb=$1'),
258 MAG_IMG_RIGHT => array( 1, 'right' ),
259 MAG_IMG_LEFT => array( 1, 'left' ),
260 MAG_IMG_NONE => array( 1, 'none' ),
261 MAG_IMG_WIDTH => array( 1, '$1px' ),
262 MAG_IMG_CENTER => array( 1, 'center', 'centre' ),
263 MAG_IMG_FRAMED => array( 1, 'framed', 'enframed', 'frame' ),
264 MAG_INT => array( 0, 'INT:' ),
265 MAG_SITENAME => array( 1, 'SITENAME' ),
266 MAG_NS => array( 0, 'NS:' ),
267 MAG_LOCALURL => array( 0, 'LOCALURL:' ),
268 MAG_LOCALURLE => array( 0, 'LOCALURLE:' ),
269 MAG_SERVER => array( 0, 'SERVER' ),
270 MAG_SERVERNAME => array( 0, 'SERVERNAME' ),
271 MAG_SCRIPTPATH => array( 0, 'SCRIPTPATH' ),
272 MAG_GRAMMAR => array( 0, 'GRAMMAR:' ),
273 MAG_NOTITLECONVERT => array( 0, '__NOTITLECONVERT__', '__NOTC__'),
274 MAG_NOCONTENTCONVERT => array( 0, '__NOCONTENTCONVERT__', '__NOCC__'),
275 MAG_CURRENTWEEK => array( 1, 'CURRENTWEEK' ),
276 MAG_CURRENTDOW => array( 1, 'CURRENTDOW' ),
277 MAG_REVISIONID => array( 1, 'REVISIONID' ),
278 MAG_PLURAL => array( 0, 'PLURAL:' ),
279 MAG_FULLURL => array( 0, 'FULLURL:' ),
280 MAG_FULLURLE => array( 0, 'FULLURLE:' ),
281 MAG_LCFIRST => array( 0, 'LCFIRST:' ),
282 MAG_UCFIRST => array( 0, 'UCFIRST:' ),
283 MAG_LC => array( 0, 'LC:' ),
284 MAG_UC => array( 0, 'UC:' ),
285 MAG_RAW => array( 0, 'RAW:' ),
286 MAG_DISPLAYTITLE => array( 1, 'DISPLAYTITLE' ),
287 MAG_RAWSUFFIX => array( 1, 'R' ),
288 MAG_NEWSECTIONLINK => array( 1, '__NEWSECTIONLINK__' ),
289 MAG_CURRENTVERSION => array( 1, 'CURRENTVERSION' ),
290 MAG_URLENCODE => array( 0, 'URLENCODE:' ),
291 MAG_CURRENTTIMESTAMP => array( 1, 'CURRENTTIMESTAMP' ),
292 MAG_DIRECTIONMARK => array( 1, 'DIRECTIONMARK', 'DIRMARK' ),
293 MAG_LANGUAGE => array( 0, '#LANGUAGE:' ),
294 MAG_CONTENTLANGUAGE => array( 1, 'CONTENTLANGUAGE', 'CONTENTLANG' ),
295 MAG_PAGESINNAMESPACE => array( 1, 'PAGESINNAMESPACE:', 'PAGESINNS:' ),
296 MAG_NUMBEROFADMINS => array( 1, 'NUMBEROFADMINS' ),
297 );
298
299 if (!$wgCachedMessageArrays) {
300 require_once('Messages.php');
301 }
302
303 /* a fake language converter */
304 class fakeConverter {
305 var $mLang;
306 function fakeConverter($langobj) {$this->mLang = $langobj;}
307 function convert($t, $i) {return $t;}
308 function parserConvert($t, $p) {return $t;}
309 function getVariants() { return array( $this->mLang->getCode() ); }
310 function getPreferredVariant() {return $this->mLang->getCode(); }
311 function findVariantLink(&$l, &$n) {}
312 function getExtraHashOptions() {return '';}
313 function getParsedTitle() {return '';}
314 function markNoConversion($text) {return $text;}
315 function convertCategoryKey( $key ) {return $key; }
316
317 }
318
319 #--------------------------------------------------------------------------
320 # Internationalisation code
321 #--------------------------------------------------------------------------
322
323 class Language {
324 var $mConverter;
325 function Language() {
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 * @public
508 * @param int $ts the time in date('YmdHis') format
509 * @param mixed $tz adjust the time by this amount (default false,
510 * mean we get user timecorrection setting)
511 * @return int
512
513 */
514 function userAdjust( $ts, $tz = false ) {
515 global $wgUser, $wgLocalTZoffset;
516
517 if (!$tz) {
518 $tz = $wgUser->getOption( 'timecorrection' );
519 }
520
521 # minutes and hours differences:
522 $minDiff = 0;
523 $hrDiff = 0;
524
525 if ( $tz === '' ) {
526 # Global offset in minutes.
527 if( isset($wgLocalTZoffset) ) {
528 $hrDiff = $wgLocalTZoffset % 60;
529 $minDiff = $wgLocalTZoffset - ($hrDiff * 60);
530 }
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 = $this->timeSeparator( $format );
642
643 $hh = substr( $ts, 8, 2 );
644 $mm = substr( $ts, 10, 2 );
645 $ss = substr( $ts, 12, 2 );
646
647 if ( $datePreference != MW_DATE_ISO ) {
648 $hh = $this->formatNum( $hh, true );
649 $mm = $this->formatNum( $mm, true );
650 //$ss = $this->formatNum( $ss, true );
651 return $hh . $sep . $mm;
652 } else {
653 return $hh . ':' . $mm . ':' . $ss;
654 }
655 }
656
657 /**
658 * Default separator character between hours, minutes, and seconds.
659 * Will be used by Language::time() for non-ISO formats.
660 * (ISO will always use a colon.)
661 * @return string
662 */
663 function timeSeparator( $format ) {
664 return ':';
665 }
666
667 /**
668 * String to insert between the time and the date in a combined
669 * string. Should include any relevant whitespace.
670 * @return string
671 */
672 function timeDateSeparator( $format ) {
673 return ', ';
674 }
675
676 /**
677 * Return true if the time should display before the date.
678 * @return bool
679 * @private
680 */
681 function timeBeforeDate() {
682 return true;
683 }
684
685 function formatMonth( $month, $format ) {
686 return $this->getMonthName( $month );
687 }
688
689 function formatDay( $day, $format ) {
690 return $this->formatNum( 0 + $day, true );
691 }
692
693 /**
694 * @public
695 * @param mixed $ts the time format which needs to be turned into a
696 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
697 * @param bool $adj whether to adjust the time output according to the
698 * user configured offset ($timecorrection)
699
700 * @param mixed $format what format to return, if it's false output the
701 * default one (default true)
702 * @param string $timecorrection the time offset as returned by
703 * validateTimeZone() in Special:Preferences
704 * @return string
705 */
706 function timeanddate( $ts, $adj = false, $format = true, $timecorrection = false) {
707 global $wgUser;
708
709 $datePreference = $this->dateFormat($format);
710 switch ( $datePreference ) {
711 case MW_DATE_ISO: return $this->date( $ts, $adj, $format, $timecorrection ) . ' ' .
712 $this->time( $ts, $adj, $format, $timecorrection );
713 default:
714 $time = $this->time( $ts, $adj, $format, $timecorrection );
715 $sep = $this->timeDateSeparator( $datePreference );
716 $date = $this->date( $ts, $adj, $format, $timecorrection );
717 return $this->timeBeforeDate( $datePreference )
718 ? $time . $sep . $date
719 : $date . $sep . $time;
720 }
721 }
722
723 function getMessage( $key ) {
724 global $wgAllMessagesEn;
725 return @$wgAllMessagesEn[$key];
726 }
727
728 function getAllMessages() {
729 global $wgAllMessagesEn;
730 return $wgAllMessagesEn;
731 }
732
733 function iconv( $in, $out, $string ) {
734 # For most languages, this is a wrapper for iconv
735 return iconv( $in, $out, $string );
736 }
737
738 function ucfirst( $string ) {
739 # For most languages, this is a wrapper for ucfirst()
740 return ucfirst( $string );
741 }
742
743 function uc( $str ) {
744 return strtoupper( $str );
745 }
746
747 function lcfirst( $s ) {
748 return strtolower( $s{0} ). substr( $s, 1 );
749 }
750
751 function lc( $str ) {
752 return strtolower( $str );
753 }
754
755 function checkTitleEncoding( $s ) {
756 global $wgInputEncoding;
757
758 # Check for UTF-8 URLs; Internet Explorer produces these if you
759 # type non-ASCII chars in the URL bar or follow unescaped links.
760 $ishigh = preg_match( '/[\x80-\xff]/', $s);
761 $isutf = ($ishigh ? preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
762 '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s ) : true );
763
764 if( ($wgInputEncoding != 'utf-8') and $ishigh and $isutf )
765 return @iconv( 'UTF-8', $wgInputEncoding, $s );
766
767 if( ($wgInputEncoding == 'utf-8') and $ishigh and !$isutf )
768 return utf8_encode( $s );
769
770 # Other languages can safely leave this function, or replace
771 # it with one to detect and convert another legacy encoding.
772 return $s;
773 }
774
775 /**
776 * Some languages have special punctuation to strip out
777 * or characters which need to be converted for MySQL's
778 * indexing to grok it correctly. Make such changes here.
779 *
780 * @param string $in
781 * @return string
782 */
783 function stripForSearch( $in ) {
784 return strtolower( $in );
785 }
786
787 function convertForSearchResult( $termsArray ) {
788 # some languages, e.g. Chinese, need to do a conversion
789 # in order for search results to be displayed correctly
790 return $termsArray;
791 }
792
793 /**
794 * Get the first character of a string. In ASCII, return
795 * first byte of the string. UTF8 and others have to
796 * overload this.
797 *
798 * @param string $s
799 * @return string
800 */
801 function firstChar( $s ) {
802 return $s[0];
803 }
804
805 function initEncoding() {
806 # Some languages may have an alternate char encoding option
807 # (Esperanto X-coding, Japanese furigana conversion, etc)
808 # If this language is used as the primary content language,
809 # an override to the defaults can be set here on startup.
810 #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
811 }
812
813 function setAltEncoding() {
814 # Some languages may have an alternate char encoding option
815 # (Esperanto X-coding, Japanese furigana conversion, etc)
816 # If 'altencoding' is checked in user prefs, this gives a
817 # chance to swap out the default encoding settings.
818 #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
819 }
820
821 function recodeForEdit( $s ) {
822 # For some languages we'll want to explicitly specify
823 # which characters make it into the edit box raw
824 # or are converted in some way or another.
825 # Note that if wgOutputEncoding is different from
826 # wgInputEncoding, this text will be further converted
827 # to wgOutputEncoding.
828 global $wgInputEncoding, $wgEditEncoding;
829 if( $wgEditEncoding == '' or
830 $wgEditEncoding == $wgInputEncoding ) {
831 return $s;
832 } else {
833 return $this->iconv( $wgInputEncoding, $wgEditEncoding, $s );
834 }
835 }
836
837 function recodeInput( $s ) {
838 # Take the previous into account.
839 global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
840 if($wgEditEncoding != "") {
841 $enc = $wgEditEncoding;
842 } else {
843 $enc = $wgOutputEncoding;
844 }
845 if( $enc == $wgInputEncoding ) {
846 return $s;
847 } else {
848 return $this->iconv( $enc, $wgInputEncoding, $s );
849 }
850 }
851
852 /**
853 * For right-to-left language support
854 *
855 * @return bool
856 */
857 function isRTL() { return false; }
858
859 /**
860 * A hidden direction mark (LRM or RLM), depending on the language direction
861 *
862 * @return string
863 */
864 function getDirMark() { return $this->isRTL() ? "\xE2\x80\x8F" : "\xE2\x80\x8E"; }
865
866 /**
867 * To allow "foo[[bar]]" to extend the link over the whole word "foobar"
868 *
869 * @return bool
870 */
871 function linkPrefixExtension() { return false; }
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 global $wgGrammarForms;
1018 if ( isset($wgGrammarForms['en'][$case][$word]) ) {
1019 return $wgGrammarForms['en'][$case][$word];
1020 }
1021 return $word;
1022 }
1023
1024 /**
1025 * Plural form transformations, needed for some languages.
1026 * For example, where are 3 form of plural in Russian and Polish,
1027 * depending on "count mod 10". See [[w:Plural]]
1028 * For English it is pretty simple.
1029 *
1030 * Invoked by putting {{plural:count|wordform1|wordform2}}
1031 * or {{plural:count|wordform1|wordform2|wordform3}}
1032 *
1033 * Example: {{plural:{{NUMBEROFARTICLES}}|article|articles}}
1034 *
1035 * @param integer $count
1036 * @param string $wordform1
1037 * @param string $wordform2
1038 * @param string $wordform3 (optional)
1039 * @return string
1040 */
1041 function convertPlural( $count, $wordform1, $wordform2, $wordform3) {
1042 return $count == '1' ? $wordform1 : $wordform2;
1043 }
1044
1045 /**
1046 * For translaing of expiry times
1047 * @param string The validated block time in English
1048 * @return Somehow translated block time
1049 * @see LanguageFi.php for example implementation
1050 */
1051 function translateBlockExpiry( $str ) {
1052
1053 $scBlockExpiryOptions = wfMsg( 'ipboptions' );
1054
1055 if ( $scBlockExpiryOptions == '-') {
1056 return $str;
1057 }
1058
1059 foreach (explode(',', $scBlockExpiryOptions) as $option) {
1060 if ( strpos($option, ":") === false )
1061 continue;
1062 list($show, $value) = explode(":", $option);
1063 if ( strcmp ( $str, $value) == 0 )
1064 return '<span title="' . htmlspecialchars($str). '">' .
1065 htmlspecialchars( trim( $show ) ) . '</span>';
1066 }
1067
1068 return $str;
1069 }
1070
1071 /**
1072 * languages like Chinese need to be segmented in order for the diff
1073 * to be of any use
1074 *
1075 * @param string $text
1076 * @return string
1077 */
1078 function segmentForDiff( $text ) {
1079 return $text;
1080 }
1081
1082 /**
1083 * and unsegment to show the result
1084 *
1085 * @param string $text
1086 * @return string
1087 */
1088 function unsegmentForDiff( $text ) {
1089 return $text;
1090 }
1091
1092 # convert text to different variants of a language.
1093 function convert( $text, $isTitle = false) {
1094 return $this->mConverter->convert($text, $isTitle);
1095 }
1096
1097 # Convert text from within Parser
1098 function parserConvert( $text, &$parser ) {
1099 return $this->mConverter->parserConvert( $text, $parser );
1100 }
1101
1102 /**
1103 * Perform output conversion on a string, and encode for safe HTML output.
1104 * @param string $text
1105 * @param bool $isTitle -- wtf?
1106 * @return string
1107 * @todo this should get integrated somewhere sane
1108 */
1109 function convertHtml( $text, $isTitle = false ) {
1110 return htmlspecialchars( $this->convert( $text, $isTitle ) );
1111 }
1112
1113 function convertCategoryKey( $key ) {
1114 return $this->mConverter->convertCategoryKey( $key );
1115 }
1116
1117 /**
1118 * get the list of variants supported by this langauge
1119 * see sample implementation in LanguageZh.php
1120 *
1121 * @return array an array of language codes
1122 */
1123 function getVariants() {
1124 return $this->mConverter->getVariants();
1125 }
1126
1127
1128 function getPreferredVariant() {
1129 return $this->mConverter->getPreferredVariant();
1130 }
1131
1132 /**
1133 * if a language supports multiple variants, it is
1134 * possible that non-existing link in one variant
1135 * actually exists in another variant. this function
1136 * tries to find it. See e.g. LanguageZh.php
1137 *
1138 * @param string $link the name of the link
1139 * @param mixed $nt the title object of the link
1140 * @return null the input parameters may be modified upon return
1141 */
1142 function findVariantLink( &$link, &$nt ) {
1143 $this->mConverter->findVariantLink($link, $nt);
1144 }
1145
1146 /**
1147 * returns language specific options used by User::getPageRenderHash()
1148 * for example, the preferred language variant
1149 *
1150 * @return string
1151 * @public
1152 */
1153 function getExtraHashOptions() {
1154 return $this->mConverter->getExtraHashOptions();
1155 }
1156
1157 /**
1158 * for languages that support multiple variants, the title of an
1159 * article may be displayed differently in different variants. this
1160 * function returns the apporiate title defined in the body of the article.
1161 *
1162 * @return string
1163 */
1164 function getParsedTitle() {
1165 return $this->mConverter->getParsedTitle();
1166 }
1167
1168 /**
1169 * Enclose a string with the "no conversion" tag. This is used by
1170 * various functions in the Parser
1171 *
1172 * @param string $text text to be tagged for no conversion
1173 * @return string the tagged text
1174 */
1175 function markNoConversion( $text ) {
1176 return $this->mConverter->markNoConversion( $text );
1177 }
1178
1179 /**
1180 * A regular expression to match legal word-trailing characters
1181 * which should be merged onto a link of the form [[foo]]bar.
1182 *
1183 * @return string
1184 * @public
1185 */
1186 function linkTrail() {
1187 return $this->getMessage( 'linktrail' );
1188 }
1189
1190 function getLangObj() {
1191 return $this;
1192 }
1193
1194 /**
1195 * Get the RFC 3066 code for this language object
1196 */
1197 function getCode() {
1198 return str_replace( '_', '-', strtolower( substr( get_class( $this ), 8 ) ) );
1199 }
1200
1201
1202 }
1203
1204 # FIXME: Merge all UTF-8 support code into Language base class.
1205 # We no longer support Latin-1 charset.
1206 require_once( 'LanguageUtf8.php' );
1207
1208 # This should fail gracefully if there's not a localization available
1209 wfSuppressWarnings();
1210 // Preload base classes to work around APC/PHP5 bug
1211 include_once( 'Language' . str_replace( '-', '_', ucfirst( $wgLanguageCode ) ) . '.deps.php' );
1212 include_once( 'Language' . str_replace( '-', '_', ucfirst( $wgLanguageCode ) ) . '.php' );
1213 wfRestoreWarnings();
1214
1215 }
1216 ?>