* (bug 5595) Localisation for Bosnian language (bs)
[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 'highlightbroken' => 1,
66 'stubthreshold' => 0,
67 'previewontop' => 1,
68 'editsection' => 1,
69 'editsectiononrightclick'=> 0,
70 'showtoc' => 1,
71 'showtoolbar' => 1,
72 'date' => 0,
73 'imagesize' => 2,
74 'thumbsize' => 2,
75 'rememberpassword' => 0,
76 'enotifwatchlistpages' => 0,
77 'enotifusertalkpages' => 1,
78 'enotifminoredits' => 0,
79 'enotifrevealaddr' => 0,
80 'shownumberswatching' => 1,
81 'fancysig' => 0,
82 'externaleditor' => 0,
83 'externaldiff' => 0,
84 'showjumplinks' => 1,
85 'numberheadings' => 0,
86 'uselivepreview' => 0,
87 );
88
89 /* private */ $wgQuickbarSettingsEn = array(
90 'None', 'Fixed left', 'Fixed right', 'Floating left', 'Floating right'
91 );
92
93 /* private */ $wgSkinNamesEn = array(
94 'standard' => 'Classic',
95 'nostalgia' => 'Nostalgia',
96 'cologneblue' => 'Cologne Blue',
97 'davinci' => 'DaVinci',
98 'mono' => 'Mono',
99 'monobook' => 'MonoBook',
100 'myskin' => 'MySkin',
101 'chick' => 'Chick'
102 );
103
104 /* private */ $wgMathNamesEn = array(
105 MW_MATH_PNG => 'mw_math_png',
106 MW_MATH_SIMPLE => 'mw_math_simple',
107 MW_MATH_HTML => 'mw_math_html',
108 MW_MATH_SOURCE => 'mw_math_source',
109 MW_MATH_MODERN => 'mw_math_modern',
110 MW_MATH_MATHML => 'mw_math_mathml'
111 );
112
113 /**
114 * Whether to use user or default setting in Language::date()
115 *
116 * NOTE: the array string values are no longer important!
117 * The actual date format functions are now called for the selection in
118 * Special:Preferences, and the 'datedefault' message for MW_DATE_DEFAULT.
119 *
120 * The array keys make up the set of formats which this language allows
121 * the user to select. It's exposed via Language::getDateFormats().
122 *
123 * @access private
124 */
125 $wgDateFormatsEn = array(
126 MW_DATE_DEFAULT => 'No preference',
127 MW_DATE_DMY => '16:12, 15 January 2001',
128 MW_DATE_MDY => '16:12, January 15, 2001',
129 MW_DATE_YMD => '16:12, 2001 January 15',
130 MW_DATE_ISO => '2001-01-15 16:12:34'
131 );
132
133 /* private */ $wgUserTogglesEn = array(
134 'highlightbroken',
135 'justify',
136 'hideminor',
137 'usenewrc',
138 'numberheadings',
139 'showtoolbar',
140 'editondblclick',
141 'editsection',
142 'editsectiononrightclick',
143 'showtoc',
144 'rememberpassword',
145 'editwidth',
146 'watchcreations',
147 'watchdefault',
148 'minordefault',
149 'previewontop',
150 'previewonfirst',
151 'nocache',
152 'enotifwatchlistpages',
153 'enotifusertalkpages',
154 'enotifminoredits',
155 'enotifrevealaddr',
156 'shownumberswatching',
157 'fancysig',
158 'externaleditor',
159 'externaldiff',
160 'showjumplinks',
161 'uselivepreview',
162 'autopatrol',
163 'forceeditsummary',
164 );
165
166 /* private */ $wgBookstoreListEn = array(
167 'AddALL' => 'http://www.addall.com/New/Partner.cgi?query=$1&type=ISBN',
168 'PriceSCAN' => 'http://www.pricescan.com/books/bookDetail.asp?isbn=$1',
169 'Barnes & Noble' => 'http://search.barnesandnoble.com/bookSearch/isbnInquiry.asp?isbn=$1',
170 'Amazon.com' => 'http://www.amazon.com/exec/obidos/ISBN=$1'
171 );
172
173 # Read language names
174 global $wgLanguageNames;
175 /** */
176 require_once( 'Names.php' );
177
178 $wgLanguageNamesEn =& $wgLanguageNames;
179
180
181 /* private */ $wgWeekdayNamesEn = array(
182 'sunday', 'monday', 'tuesday', 'wednesday', 'thursday',
183 'friday', 'saturday'
184 );
185
186
187 /* private */ $wgMonthNamesEn = array(
188 'january', 'february', 'march', 'april', 'may_long', 'june',
189 'july', 'august', 'september', 'october', 'november',
190 'december'
191 );
192 /* private */ $wgMonthNamesGenEn = array(
193 'january-gen', 'february-gen', 'march-gen', 'april-gen', 'may-gen', 'june-gen',
194 'july-gen', 'august-gen', 'september-gen', 'october-gen', 'november-gen',
195 'december-gen'
196 );
197
198 /* private */ $wgMonthAbbreviationsEn = array(
199 'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug',
200 'sep', 'oct', 'nov', 'dec'
201 );
202
203 # Note to translators:
204 # Please include the English words as synonyms. This allows people
205 # from other wikis to contribute more easily.
206 #
207 /* private */ $wgMagicWordsEn = array(
208 # ID CASE SYNONYMS
209 MAG_REDIRECT => array( 0, '#REDIRECT' ),
210 MAG_NOTOC => array( 0, '__NOTOC__' ),
211 MAG_FORCETOC => array( 0, '__FORCETOC__' ),
212 MAG_TOC => array( 0, '__TOC__' ),
213 MAG_NOEDITSECTION => array( 0, '__NOEDITSECTION__' ),
214 MAG_START => array( 0, '__START__' ),
215 MAG_CURRENTMONTH => array( 1, 'CURRENTMONTH' ),
216 MAG_CURRENTMONTHNAME => array( 1, 'CURRENTMONTHNAME' ),
217 MAG_CURRENTMONTHNAMEGEN => array( 1, 'CURRENTMONTHNAMEGEN' ),
218 MAG_CURRENTMONTHABBREV => array( 1, 'CURRENTMONTHABBREV' ),
219 MAG_CURRENTDAY => array( 1, 'CURRENTDAY' ),
220 MAG_CURRENTDAY2 => array( 1, 'CURRENTDAY2' ),
221 MAG_CURRENTDAYNAME => array( 1, 'CURRENTDAYNAME' ),
222 MAG_CURRENTYEAR => array( 1, 'CURRENTYEAR' ),
223 MAG_CURRENTTIME => array( 1, 'CURRENTTIME' ),
224 MAG_NUMBEROFARTICLES => array( 1, 'NUMBEROFARTICLES' ),
225 MAG_NUMBEROFFILES => array( 1, 'NUMBEROFFILES' ),
226 MAG_PAGENAME => array( 1, 'PAGENAME' ),
227 MAG_PAGENAMEE => array( 1, 'PAGENAMEE' ),
228 MAG_NAMESPACE => array( 1, 'NAMESPACE' ),
229 MAG_NAMESPACEE => array( 1, 'NAMESPACEE' ),
230 MAG_TALKSPACE => array( 1, 'TALKSPACE' ),
231 MAG_TALKSPACEE => array( 1, 'TALKSPACEE' ),
232 MAG_SUBJECTSPACE => array( 1, 'SUBJECTSPACE', 'ARTICLESPACE' ),
233 MAG_SUBJECTSPACEE => array( 1, 'SUBJECTSPACEE', 'ARTICLESPACEE' ),
234 MAG_FULLPAGENAME => array( 1, 'FULLPAGENAME' ),
235 MAG_FULLPAGENAMEE => array( 1, 'FULLPAGENAMEE' ),
236 MAG_SUBPAGENAME => array( 1, 'SUBPAGENAME' ),
237 MAG_SUBPAGENAMEE => array( 1, 'SUBPAGENAMEE' ),
238 MAG_TALKPAGENAME => array( 1, 'TALKPAGENAME' ),
239 MAG_TALKPAGENAMEE => array( 1, 'TALKPAGENAMEE' ),
240 MAG_SUBJECTPAGENAME => array( 1, 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ),
241 MAG_SUBJECTPAGENAMEE => array( 1, 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ),
242 MAG_MSG => array( 0, 'MSG:' ),
243 MAG_SUBST => array( 0, 'SUBST:' ),
244 MAG_MSGNW => array( 0, 'MSGNW:' ),
245 MAG_END => array( 0, '__END__' ),
246 MAG_IMG_THUMBNAIL => array( 1, 'thumbnail', 'thumb' ),
247 MAG_IMG_MANUALTHUMB => array( 1, 'thumbnail=$1', 'thumb=$1'),
248 MAG_IMG_RIGHT => array( 1, 'right' ),
249 MAG_IMG_LEFT => array( 1, 'left' ),
250 MAG_IMG_NONE => array( 1, 'none' ),
251 MAG_IMG_WIDTH => array( 1, '$1px' ),
252 MAG_IMG_CENTER => array( 1, 'center', 'centre' ),
253 MAG_IMG_FRAMED => array( 1, 'framed', 'enframed', 'frame' ),
254 MAG_INT => array( 0, 'INT:' ),
255 MAG_SITENAME => array( 1, 'SITENAME' ),
256 MAG_NS => array( 0, 'NS:' ),
257 MAG_LOCALURL => array( 0, 'LOCALURL:' ),
258 MAG_LOCALURLE => array( 0, 'LOCALURLE:' ),
259 MAG_SERVER => array( 0, 'SERVER' ),
260 MAG_SERVERNAME => array( 0, 'SERVERNAME' ),
261 MAG_SCRIPTPATH => array( 0, 'SCRIPTPATH' ),
262 MAG_GRAMMAR => array( 0, 'GRAMMAR:' ),
263 MAG_NOTITLECONVERT => array( 0, '__NOTITLECONVERT__', '__NOTC__'),
264 MAG_NOCONTENTCONVERT => array( 0, '__NOCONTENTCONVERT__', '__NOCC__'),
265 MAG_CURRENTWEEK => array( 1, 'CURRENTWEEK' ),
266 MAG_CURRENTDOW => array( 1, 'CURRENTDOW' ),
267 MAG_REVISIONID => array( 1, 'REVISIONID' ),
268 MAG_PLURAL => array( 0, 'PLURAL:' ),
269 MAG_FULLURL => array( 0, 'FULLURL:' ),
270 MAG_FULLURLE => array( 0, 'FULLURLE:' ),
271 MAG_LCFIRST => array( 0, 'LCFIRST:' ),
272 MAG_UCFIRST => array( 0, 'UCFIRST:' ),
273 MAG_LC => array( 0, 'LC:' ),
274 MAG_UC => array( 0, 'UC:' ),
275 MAG_RAW => array( 0, 'RAW:' ),
276 MAG_DISPLAYTITLE => array( 1, 'DISPLAYTITLE' ),
277 );
278
279 if (!$wgCachedMessageArrays) {
280 require_once('Messages.php');
281 }
282
283 /* a fake language converter */
284 class fakeConverter {
285 var $mLang;
286 function fakeConverter($langobj) {$this->mLang = $langobj;}
287 function convert($t, $i) {return $t;}
288 function parserConvert($t, $p) {return $t;}
289 function getVariants() { return array( $this->mLang->getCode() ); }
290 function getPreferredVariant() {return $this->mLang->getCode(); }
291 function findVariantLink(&$l, &$n) {}
292 function getExtraHashOptions() {return '';}
293 function getParsedTitle() {return '';}
294 function markNoConversion($text) {return $text;}
295 function convertCategoryKey( $key ) {return $key; }
296
297 }
298
299 #--------------------------------------------------------------------------
300 # Internationalisation code
301 #--------------------------------------------------------------------------
302
303 class Language {
304 var $mConverter;
305 function Language() {
306
307 # Copies any missing values in the specified arrays from En to the current language
308 $fillin = array( 'wgSysopSpecialPages', 'wgValidSpecialPages', 'wgDeveloperSpecialPages' );
309 $name = get_class( $this );
310
311 if( strpos( $name, 'language' ) == 0){
312 $lang = ucfirst( substr( $name, 8 ) );
313 foreach( $fillin as $arrname ){
314 $langver = "{$arrname}{$lang}";
315 $enver = "{$arrname}En";
316 if( ! isset( $GLOBALS[$langver] ) || ! isset( $GLOBALS[$enver] ))
317 continue;
318 foreach($GLOBALS[$enver] as $spage => $text){
319 if( ! isset( $GLOBALS[$langver][$spage] ) )
320 $GLOBALS[$langver][$spage] = $text;
321 }
322 }
323 }
324 $this->mConverter = new fakeConverter($this);
325 }
326
327 /**
328 * Exports the default user options as defined in
329 * $wgDefaultUserOptionsEn, user preferences can override some of these
330 * depending on what's in (Local|Default)Settings.php and some defines.
331 *
332 * @return array
333 */
334 function getDefaultUserOptions() {
335 global $wgDefaultUserOptionsEn ;
336 return $wgDefaultUserOptionsEn ;
337 }
338
339 /**
340 * Exports $wgBookstoreListEn
341 * @return array
342 */
343 function getBookstoreList() {
344 global $wgBookstoreListEn ;
345 return $wgBookstoreListEn ;
346 }
347
348 /**
349 * @return array
350 */
351 function getNamespaces() {
352 global $wgNamespaceNamesEn;
353 return $wgNamespaceNamesEn;
354 }
355
356 /**
357 * A convenience function that returns the same thing as
358 * getNamespaces() except with the array values changed to ' '
359 * where it found '_', useful for producing output to be displayed
360 * e.g. in <select> forms.
361 *
362 * @return array
363 */
364 function getFormattedNamespaces() {
365 $ns = $this->getNamespaces();
366 foreach($ns as $k => $v) {
367 $ns[$k] = strtr($v, '_', ' ');
368 }
369 return $ns;
370 }
371
372 /**
373 * Get a namespace value by key
374 * <code>
375 * $mw_ns = $wgContLang->getNsText( NS_MEDIAWIKI );
376 * echo $mw_ns; // prints 'MediaWiki'
377 * </code>
378 *
379 * @param int $index the array key of the namespace to return
380 * @return mixed, string if the namespace value exists, otherwise false
381 */
382 function getNsText( $index ) {
383 $ns = $this->getNamespaces();
384 return isset( $ns[$index] ) ? $ns[$index] : false;
385 }
386
387 /**
388 * A convenience function that returns the same thing as
389 * getNsText() except with '_' changed to ' ', useful for
390 * producing output.
391 *
392 * @return array
393 */
394 function getFormattedNsText( $index ) {
395 $ns = $this->getNsText( $index );
396 return strtr($ns, '_', ' ');
397 }
398
399 /**
400 * Get a namespace key by value, case insensetive.
401 *
402 * @param string $text
403 * @return mixed An integer if $text is a valid value otherwise false
404 */
405 function getNsIndex( $text ) {
406 $ns = $this->getNamespaces();
407
408 foreach ( $ns as $i => $n ) {
409 if ( strcasecmp( $n, $text ) == 0)
410 return $i;
411 }
412 return false;
413 }
414
415 /**
416 * short names for language variants used for language conversion links.
417 *
418 * @param string $code
419 * @return string
420 */
421 function getVariantname( $code ) {
422 return wfMsg( "variantname-$code" );
423 }
424
425 function specialPage( $name ) {
426 return $this->getNsText(NS_SPECIAL) . ':' . $name;
427 }
428
429 function getQuickbarSettings() {
430 global $wgQuickbarSettingsEn;
431 return $wgQuickbarSettingsEn;
432 }
433
434 function getSkinNames() {
435 global $wgSkinNamesEn;
436 return $wgSkinNamesEn;
437 }
438
439 function getMathNames() {
440 global $wgMathNamesEn;
441 return $wgMathNamesEn;
442 }
443
444 function getDateFormats() {
445 global $wgDateFormatsEn;
446 return $wgDateFormatsEn;
447 }
448
449 function getUserToggles() {
450 global $wgUserTogglesEn;
451 return $wgUserTogglesEn;
452 }
453
454 function getUserToggle( $tog ) {
455 return wfMsg( "tog-$tog" );
456 }
457
458 function getLanguageNames() {
459 global $wgLanguageNamesEn;
460 return $wgLanguageNamesEn;
461 }
462
463 function getLanguageName( $code ) {
464 global $wgLanguageNamesEn;
465 if ( ! array_key_exists( $code, $wgLanguageNamesEn ) ) {
466 return '';
467 }
468 return $wgLanguageNamesEn[$code];
469 }
470
471 function getMonthName( $key ) {
472 global $wgMonthNamesEn, $wgContLang;
473 // see who called us and use the correct message function
474 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
475 return wfMsgForContent($wgMonthNamesEn[$key-1]);
476 else
477 return wfMsg($wgMonthNamesEn[$key-1]);
478 }
479
480 /* by default we just return base form */
481 function getMonthNameGen( $key ) {
482 return $this->getMonthName( $key );
483 }
484
485 function getMonthAbbreviation( $key ) {
486 global $wgMonthAbbreviationsEn, $wgContLang;
487 // see who called us and use the correct message function
488 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
489 return wfMsgForContent(@$wgMonthAbbreviationsEn[$key-1]);
490 else
491 return wfMsg(@$wgMonthAbbreviationsEn[$key-1]);
492 }
493
494 function getWeekdayName( $key ) {
495 global $wgWeekdayNamesEn, $wgContLang;
496 // see who called us and use the correct message function
497 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
498 return wfMsgForContent($wgWeekdayNamesEn[$key-1]);
499 else
500 return wfMsg($wgWeekdayNamesEn[$key-1]);
501 }
502
503 /**
504 * Used by date() and time() to adjust the time output.
505 * @access public
506 * @param int $ts the time in date('YmdHis') format
507 * @param mixed $tz adjust the time by this amount (default false)
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 if ( $tz === '' ) {
519 $hrDiff = isset( $wgLocalTZoffset ) ? $wgLocalTZoffset : 0;
520 $minDiff = 0;
521 } elseif ( strpos( $tz, ':' ) !== false ) {
522 $tzArray = explode( ':', $tz );
523 $hrDiff = intval($tzArray[0]);
524 $minDiff = intval($hrDiff < 0 ? -$tzArray[1] : $tzArray[1]);
525 } else {
526 $hrDiff = intval( $tz );
527 }
528 if ( 0 == $hrDiff && 0 == $minDiff ) { return $ts; }
529
530 $t = mktime( (
531 (int)substr( $ts, 8, 2) ) + $hrDiff, # Hours
532 (int)substr( $ts, 10, 2 ) + $minDiff, # Minutes
533 (int)substr( $ts, 12, 2 ), # Seconds
534 (int)substr( $ts, 4, 2 ), # Month
535 (int)substr( $ts, 6, 2 ), # Day
536 (int)substr( $ts, 0, 4 ) ); #Year
537 return date( 'YmdHis', $t );
538 }
539
540 /**
541 * This is meant to be used by time(), date(), and timeanddate() to get
542 * the date preference they're supposed to use, it should be used in
543 * all children.
544 *
545 *<code>
546 * function timeanddate([...], $format = true) {
547 * $datePreference = $this->dateFormat($format);
548 * [...]
549 *</code>
550 *
551 * @param mixed $usePrefs: if true, the user's preference is used
552 * if false, the site/language default is used
553 * if int/string, assumed to be a format.
554 * @return string
555 */
556 function dateFormat( $usePrefs = true ) {
557 global $wgUser;
558
559 if( is_bool( $usePrefs ) ) {
560 if( $usePrefs ) {
561 $datePreference = $wgUser->getOption( 'date' );
562 } else {
563 $options = $this->getDefaultUserOptions();
564 $datePreference = (string)$options['date'];
565 }
566 } else {
567 $datePreference = (string)$usePrefs;
568 }
569
570 // return int
571 if( $datePreference == '' ) {
572 return MW_DATE_DEFAULT;
573 }
574
575 return $datePreference;
576 }
577
578 /**
579 * @access public
580 * @param mixed $ts the time format which needs to be turned into a
581 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
582 * @param bool $adj whether to adjust the time output according to the
583 * user configured offset ($timecorrection)
584 * @param mixed $format true to use user's date format preference
585 * @param string $timecorrection the time offset as returned by
586 * validateTimeZone() in Special:Preferences
587 * @return string
588 */
589 function date( $ts, $adj = false, $format = true, $timecorrection = false ) {
590 global $wgUser, $wgAmericanDates;
591
592 if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
593
594 $datePreference = $this->dateFormat( $format );
595 if( $datePreference == MW_DATE_DEFAULT ) {
596 $datePreference = $wgAmericanDates ? MW_DATE_MDY : MW_DATE_DMY;
597 }
598
599 $month = $this->formatMonth( substr( $ts, 4, 2 ), $datePreference );
600 $day = $this->formatDay( substr( $ts, 6, 2 ), $datePreference );
601 $year = $this->formatNum( substr( $ts, 0, 4 ), true );
602
603 switch( $datePreference ) {
604 case MW_DATE_DMY: return "$day $month $year";
605 case MW_DATE_YMD: return "$year $month $day";
606 case MW_DATE_ISO: return substr($ts, 0, 4). '-' . substr($ts, 4, 2). '-' .substr($ts, 6, 2);
607 default: return "$month $day, $year";
608 }
609 }
610
611 /**
612 * @access public
613 * @param mixed $ts the time format which needs to be turned into a
614 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
615 * @param bool $adj whether to adjust the time output according to the
616 * user configured offset ($timecorrection)
617 * @param mixed $format true to use user's date format preference
618 * @param string $timecorrection the time offset as returned by
619 * validateTimeZone() in Special:Preferences
620 * @return string
621 */
622 function time( $ts, $adj = false, $format = true, $timecorrection = false ) {
623 global $wgUser;
624
625 if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
626 $datePreference = $this->dateFormat( $format );
627
628 $sep = ($datePreference == MW_DATE_ISO)
629 ? ':'
630 : $this->timeSeparator( $format );
631
632 $t = substr( $ts, 8, 2 ) . $sep . substr( $ts, 10, 2 );
633
634 if ( $datePreference == MW_DATE_ISO ) {
635 $t .= $sep . substr( $ts, 12, 2 );
636 }
637 return $t;
638 }
639
640 /**
641 * Default separator character between hours, minutes, and seconds.
642 * Will be used by Language::time() for non-ISO formats.
643 * (ISO will always use a colon.)
644 * @return string
645 */
646 function timeSeparator( $format ) {
647 return ':';
648 }
649
650 /**
651 * String to insert between the time and the date in a combined
652 * string. Should include any relevant whitespace.
653 * @return string
654 */
655 function timeDateSeparator( $format ) {
656 return ', ';
657 }
658
659 /**
660 * Return true if the time should display before the date.
661 * @return bool
662 * @access private
663 */
664 function timeBeforeDate() {
665 return true;
666 }
667
668 function formatMonth( $month, $format ) {
669 return $this->getMonthName( $month );
670 }
671
672 function formatDay( $day, $format ) {
673 return $this->formatNum( 0 + $day );
674 }
675
676 /**
677 * @access public
678 * @param mixed $ts the time format which needs to be turned into a
679 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
680 * @param bool $adj whether to adjust the time output according to the
681 * user configured offset ($timecorrection)
682
683 * @param mixed $format what format to return, if it's false output the
684 * default one (default true)
685 * @param string $timecorrection the time offset as returned by
686 * validateTimeZone() in Special:Preferences
687 * @return string
688 */
689 function timeanddate( $ts, $adj = false, $format = true, $timecorrection = false) {
690 global $wgUser;
691
692 $datePreference = $this->dateFormat($format);
693 switch ( $datePreference ) {
694 case MW_DATE_ISO: return $this->date( $ts, $adj, $format, $timecorrection ) . ' ' .
695 $this->time( $ts, $adj, $format, $timecorrection );
696 default:
697 $time = $this->time( $ts, $adj, $format, $timecorrection );
698 $sep = $this->timeDateSeparator( $datePreference );
699 $date = $this->date( $ts, $adj, $format, $timecorrection );
700 return $this->timeBeforeDate( $datePreference )
701 ? $time . $sep . $date
702 : $date . $sep . $time;
703 }
704 }
705
706 function getMessage( $key ) {
707 global $wgAllMessagesEn;
708 return @$wgAllMessagesEn[$key];
709 }
710
711 function getAllMessages() {
712 global $wgAllMessagesEn;
713 return $wgAllMessagesEn;
714 }
715
716 function iconv( $in, $out, $string ) {
717 # For most languages, this is a wrapper for iconv
718 return iconv( $in, $out, $string );
719 }
720
721 function ucfirst( $string ) {
722 # For most languages, this is a wrapper for ucfirst()
723 return ucfirst( $string );
724 }
725
726 function uc( $str ) {
727 return strtoupper( $str );
728 }
729
730 function lcfirst( $s ) {
731 return strtolower( $s{0} ). substr( $s, 1 );
732 }
733
734 function lc( $str ) {
735 return strtolower( $str );
736 }
737
738 function checkTitleEncoding( $s ) {
739 global $wgInputEncoding;
740
741 # Check for UTF-8 URLs; Internet Explorer produces these if you
742 # type non-ASCII chars in the URL bar or follow unescaped links.
743 $ishigh = preg_match( '/[\x80-\xff]/', $s);
744 $isutf = ($ishigh ? preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
745 '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s ) : true );
746
747 if( ($wgInputEncoding != 'utf-8') and $ishigh and $isutf )
748 return @iconv( 'UTF-8', $wgInputEncoding, $s );
749
750 if( ($wgInputEncoding == 'utf-8') and $ishigh and !$isutf )
751 return utf8_encode( $s );
752
753 # Other languages can safely leave this function, or replace
754 # it with one to detect and convert another legacy encoding.
755 return $s;
756 }
757
758 /**
759 * Some languages have special punctuation to strip out
760 * or characters which need to be converted for MySQL's
761 * indexing to grok it correctly. Make such changes here.
762 *
763 * @param string $in
764 * @return string
765 */
766 function stripForSearch( $in ) {
767 return strtolower( $in );
768 }
769
770 function convertForSearchResult( $termsArray ) {
771 # some languages, e.g. Chinese, need to do a conversion
772 # in order for search results to be displayed correctly
773 return $termsArray;
774 }
775
776 /**
777 * Get the first character of a string. In ASCII, return
778 * first byte of the string. UTF8 and others have to
779 * overload this.
780 *
781 * @param string $s
782 * @return string
783 */
784 function firstChar( $s ) {
785 return $s[0];
786 }
787
788 function initEncoding() {
789 # Some languages may have an alternate char encoding option
790 # (Esperanto X-coding, Japanese furigana conversion, etc)
791 # If this language is used as the primary content language,
792 # an override to the defaults can be set here on startup.
793 #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
794 }
795
796 function setAltEncoding() {
797 # Some languages may have an alternate char encoding option
798 # (Esperanto X-coding, Japanese furigana conversion, etc)
799 # If 'altencoding' is checked in user prefs, this gives a
800 # chance to swap out the default encoding settings.
801 #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
802 }
803
804 function recodeForEdit( $s ) {
805 # For some languages we'll want to explicitly specify
806 # which characters make it into the edit box raw
807 # or are converted in some way or another.
808 # Note that if wgOutputEncoding is different from
809 # wgInputEncoding, this text will be further converted
810 # to wgOutputEncoding.
811 global $wgInputEncoding, $wgEditEncoding;
812 if( $wgEditEncoding == '' or
813 $wgEditEncoding == $wgInputEncoding ) {
814 return $s;
815 } else {
816 return $this->iconv( $wgInputEncoding, $wgEditEncoding, $s );
817 }
818 }
819
820 function recodeInput( $s ) {
821 # Take the previous into account.
822 global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
823 if($wgEditEncoding != "") {
824 $enc = $wgEditEncoding;
825 } else {
826 $enc = $wgOutputEncoding;
827 }
828 if( $enc == $wgInputEncoding ) {
829 return $s;
830 } else {
831 return $this->iconv( $enc, $wgInputEncoding, $s );
832 }
833 }
834
835 /**
836 * For right-to-left language support
837 *
838 * @return bool
839 */
840 function isRTL() { return false; }
841
842 /**
843 * To allow "foo[[bar]]" to extend the link over the whole word "foobar"
844 *
845 * @return bool
846 */
847 function linkPrefixExtension() { return false; }
848
849
850 function &getMagicWords() {
851 global $wgMagicWordsEn;
852 return $wgMagicWordsEn;
853 }
854
855 # Fill a MagicWord object with data from here
856 function getMagic( &$mw ) {
857 $raw = $this->getMagicWords();
858
859 wfRunHooks( 'LanguageGetMagic', array( &$raw ) );
860
861 if( !isset( $raw[$mw->mId] ) ) {
862 # Fall back to English if local list is incomplete
863 $raw =& Language::getMagicWords();
864 }
865 $rawEntry = $raw[$mw->mId];
866 $mw->mCaseSensitive = $rawEntry[0];
867 $mw->mSynonyms = array_slice( $rawEntry, 1 );
868 }
869
870 /**
871 * Italic is unsuitable for some languages
872 *
873 * @access public
874 *
875 * @param string $text The text to be emphasized.
876 * @return string
877 */
878 function emphasize( $text ) {
879 return "<em>$text</em>";
880 }
881
882 /**
883 * This function enables formatting of numbers, it should only come
884 * into effect when the $wgTranslateNumerals variable is TRUE.
885 *
886 * Normally we output all numbers in plain en_US style, that is
887 * 293,291.235 for twohundredninetythreethousand-twohundredninetyone
888 * point twohundredthirtyfive. However this is not sutable for all
889 * languages, some such as Pakaran want ੨੯੩,੨੯੫.੨੩੫ and others such as
890 * Icelandic just want to use commas instead of dots, and dots instead
891 * of commas like "293.291,235".
892 *
893 * An example of this function being called:
894 * <code>
895 * wfMsg( 'message', $wgLang->formatNum( $num ) )
896 * </code>
897 *
898 * See LanguageGu.php for the Gujarati implementation and
899 * LanguageIs.php for the , => . and . => , implementation.
900 *
901 * @todo check if it's viable to use localeconv() for the decimal
902 * seperator thing.
903 * @access public
904 * @param mixed $number the string to be formatted, should be an integer or
905 * a floating point number.
906 * @param bool $year are we being passed a year? (turns off commafication)
907 * @return mixed whatever we're fed if it's a year, a string otherwise.
908 */
909 function formatNum( $number, $year = false ) {
910 return $year ? $number : $this->commafy($number);
911 }
912
913 /**
914 * Adds commas to a given number
915 *
916 * @param mixed $_
917 * @return string
918 */
919 function commafy($_) {
920 return strrev((string)preg_replace('/(\d{3})(?=\d)(?!\d*\.)/','$1,',strrev($_)));
921 }
922
923 /**
924 * For the credit list in includes/Credits.php (action=credits)
925 *
926 * @param array $l
927 * @return string
928 */
929 function listToText( $l ) {
930 $s = '';
931 $m = count($l) - 1;
932 for ($i = $m; $i >= 0; $i--) {
933 if ($i == $m) {
934 $s = $l[$i];
935 } else if ($i == $m - 1) {
936 $s = $l[$i] . ' ' . wfMsg('and') . ' ' . $s;
937 } else {
938 $s = $l[$i] . ', ' . $s;
939 }
940 }
941 return $s;
942 }
943
944 # Crop a string from the beginning or end to a certain number of bytes.
945 # (Bytes are used because our storage has limited byte lengths for some
946 # columns in the database.) Multibyte charsets will need to make sure that
947 # only whole characters are included!
948 #
949 # $length does not include the optional ellipsis.
950 # If $length is negative, snip from the beginning
951 function truncate( $string, $length, $ellipsis = '' ) {
952 if( $length == 0 ) {
953 return $ellipsis;
954 }
955 if ( strlen( $string ) <= abs( $length ) ) {
956 return $string;
957 }
958 if( $length > 0 ) {
959 $string = substr( $string, 0, $length );
960 return $string . $ellipsis;
961 } else {
962 $string = substr( $string, $length );
963 return $ellipsis . $string;
964 }
965 }
966
967 /**
968 * Grammatical transformations, needed for inflected languages
969 * Invoked by putting {{grammar:case|word}} in a message
970 *
971 * @param string $word
972 * @param string $case
973 * @return string
974 */
975 function convertGrammar( $word, $case ) {
976 return $word;
977 }
978
979 /**
980 * Plural form transformations, needed for some languages.
981 * For example, where are 3 form of plural in Russian and Polish,
982 * depending on "count mod 10". See [[w:Plural]]
983 * For English it is pretty simple.
984 *
985 * Invoked by putting {{plural:count|wordform1|wordform2}}
986 * or {{plural:count|wordform1|wordform2|wordform3}}
987 *
988 * Example: {{plural:{{NUMBEROFARTICLES}}|article|articles}}
989 *
990 * @param integer $count
991 * @param string $wordform1
992 * @param string $wordform2
993 * @param string $wordform3 (optional)
994 * @return string
995 */
996 function convertPlural( $count, $wordform1, $wordform2, $wordform3) {
997 return $count == '1' ? $wordform1 : $wordform2;
998 }
999
1000 /**
1001 * For translaing of expiry times
1002 * @param string The validated block time in English
1003 * @return Somehow translated block time
1004 * @see LanguageFi.php for example implementation
1005 */
1006 function translateBlockExpiry( $str ) {
1007
1008 $scBlockExpiryOptions = wfMsg( 'ipboptions' );
1009
1010 if ( $scBlockExpiryOptions == '-') {
1011 return $str;
1012 }
1013
1014 foreach (explode(',', $scBlockExpiryOptions) as $option) {
1015 if ( strpos($option, ":") === false )
1016 continue;
1017 list($show, $value) = explode(":", $option);
1018 if ( strcmp ( $str, $value) == 0 )
1019 return '<span title="' . htmlspecialchars($str). '">' .
1020 htmlspecialchars( trim( $show ) ) . '</span>';
1021 }
1022
1023 return $str;
1024 }
1025
1026 /**
1027 * languages like Chinese need to be segmented in order for the diff
1028 * to be of any use
1029 *
1030 * @param string $text
1031 * @return string
1032 */
1033 function segmentForDiff( $text ) {
1034 return $text;
1035 }
1036
1037 /**
1038 * and unsegment to show the result
1039 *
1040 * @param string $text
1041 * @return string
1042 */
1043 function unsegmentForDiff( $text ) {
1044 return $text;
1045 }
1046
1047 # convert text to different variants of a language.
1048 function convert( $text, $isTitle = false) {
1049 return $this->mConverter->convert($text, $isTitle);
1050 }
1051
1052 # Convert text from within Parser
1053 function parserConvert( $text, &$parser ) {
1054 return $this->mConverter->parserConvert( $text, $parser );
1055 }
1056
1057 /**
1058 * Perform output conversion on a string, and encode for safe HTML output.
1059 * @param string $text
1060 * @param bool $isTitle -- wtf?
1061 * @return string
1062 * @todo this should get integrated somewhere sane
1063 */
1064 function convertHtml( $text, $isTitle = false ) {
1065 return htmlspecialchars( $this->convert( $text, $isTitle ) );
1066 }
1067
1068 function convertCategoryKey( $key ) {
1069 return $this->mConverter->convertCategoryKey( $key );
1070 }
1071
1072 /**
1073 * get the list of variants supported by this langauge
1074 * see sample implementation in LanguageZh.php
1075 *
1076 * @return array an array of language codes
1077 */
1078 function getVariants() {
1079 return $this->mConverter->getVariants();
1080 }
1081
1082
1083 function getPreferredVariant() {
1084 return $this->mConverter->getPreferredVariant();
1085 }
1086
1087 /**
1088 * if a language supports multiple variants, it is
1089 * possible that non-existing link in one variant
1090 * actually exists in another variant. this function
1091 * tries to find it. See e.g. LanguageZh.php
1092 *
1093 * @param string $link the name of the link
1094 * @param mixed $nt the title object of the link
1095 * @return null the input parameters may be modified upon return
1096 */
1097 function findVariantLink( &$link, &$nt ) {
1098 $this->mConverter->findVariantLink($link, $nt);
1099 }
1100
1101 /**
1102 * returns language specific options used by User::getPageRenderHash()
1103 * for example, the preferred language variant
1104 *
1105 * @return string
1106 * @access public
1107 */
1108 function getExtraHashOptions() {
1109 return $this->mConverter->getExtraHashOptions();
1110 }
1111
1112 /**
1113 * for languages that support multiple variants, the title of an
1114 * article may be displayed differently in different variants. this
1115 * function returns the apporiate title defined in the body of the article.
1116 *
1117 * @return string
1118 */
1119 function getParsedTitle() {
1120 return $this->mConverter->getParsedTitle();
1121 }
1122
1123 /**
1124 * Enclose a string with the "no conversion" tag. This is used by
1125 * various functions in the Parser
1126 *
1127 * @param string $text text to be tagged for no conversion
1128 * @return string the tagged text
1129 */
1130 function markNoConversion( $text ) {
1131 return $this->mConverter->markNoConversion( $text );
1132 }
1133
1134 /**
1135 * A regular expression to match legal word-trailing characters
1136 * which should be merged onto a link of the form [[foo]]bar.
1137 *
1138 * @return string
1139 * @access public
1140 */
1141 function linkTrail() {
1142 return $this->getMessage( 'linktrail' );
1143 }
1144
1145 function getLangObj() {
1146 return $this;
1147 }
1148
1149 /**
1150 * Get the RFC 3066 code for this language object
1151 */
1152 function getCode() {
1153 return str_replace( '_', '-', strtolower( substr( get_class( $this ), 8 ) ) );
1154 }
1155
1156
1157 }
1158
1159 # FIXME: Merge all UTF-8 support code into Language base class.
1160 # We no longer support Latin-1 charset.
1161 require_once( 'LanguageUtf8.php' );
1162
1163 # This should fail gracefully if there's not a localization available
1164 wfSuppressWarnings();
1165 // Preload base classes to work around APC/PHP5 bug
1166 include_once( 'Language' . str_replace( '-', '_', ucfirst( $wgLanguageCode ) ) . '.deps.php' );
1167 include_once( 'Language' . str_replace( '-', '_', ucfirst( $wgLanguageCode ) ) . '.php' );
1168 wfRestoreWarnings();
1169
1170 }
1171 ?>