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