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