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