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