* (bug 5895) Update for Dutch language (nl)
[mediawiki.git] / languages / Language.php
blob17b5d12fc03f0bb5b78611ab04d46ac3ec20e102
1 <?php
2 /**
3 * @package MediaWiki
4 * @subpackage Language
5 */
7 if( defined( 'MEDIAWIKI' ) ) {
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
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.
21 #--------------------------------------------------------------------------
22 # Language-specific text
23 #--------------------------------------------------------------------------
25 if($wgMetaNamespace === FALSE)
26 $wgMetaNamespace = str_replace( ' ', '_', $wgSitename );
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',
49 if(isset($wgExtraNamespaces)) {
50 $wgNamespaceNamesEn=$wgNamespaceNamesEn+$wgExtraNamespaces;
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,
91 /* private */ $wgQuickbarSettingsEn = array(
92 'None', 'Fixed left', 'Fixed right', 'Floating left', 'Floating right'
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'
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'
116 * Whether to use user or default setting in Language::date()
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.
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().
125 * @private
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'
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',
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'
178 # Read language names
179 global $wgLanguageNames;
180 /** */
181 require_once( 'Names.php' );
183 $wgLanguageNamesEn =& $wgLanguageNames;
186 /* private */ $wgWeekdayNamesEn = array(
187 'sunday', 'monday', 'tuesday', 'wednesday', 'thursday',
188 'friday', 'saturday'
192 /* private */ $wgMonthNamesEn = array(
193 'january', 'february', 'march', 'april', 'may_long', 'june',
194 'july', 'august', 'september', 'october', 'november',
195 'december'
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'
203 /* private */ $wgMonthAbbreviationsEn = array(
204 'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug',
205 'sep', 'oct', 'nov', 'dec'
208 # Note to translators:
209 # Please include the English words as synonyms. This allows people
210 # from other wikis to contribute more easily.
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_NUMBEROFARTICLES => array( 1, 'NUMBEROFARTICLES' ),
230 MAG_NUMBEROFFILES => array( 1, 'NUMBEROFFILES' ),
231 MAG_NUMBEROFUSERS => array( 1, 'NUMBEROFUSERS' ),
232 MAG_PAGENAME => array( 1, 'PAGENAME' ),
233 MAG_PAGENAMEE => array( 1, 'PAGENAMEE' ),
234 MAG_NAMESPACE => array( 1, 'NAMESPACE' ),
235 MAG_NAMESPACEE => array( 1, 'NAMESPACEE' ),
236 MAG_TALKSPACE => array( 1, 'TALKSPACE' ),
237 MAG_TALKSPACEE => array( 1, 'TALKSPACEE' ),
238 MAG_SUBJECTSPACE => array( 1, 'SUBJECTSPACE', 'ARTICLESPACE' ),
239 MAG_SUBJECTSPACEE => array( 1, 'SUBJECTSPACEE', 'ARTICLESPACEE' ),
240 MAG_FULLPAGENAME => array( 1, 'FULLPAGENAME' ),
241 MAG_FULLPAGENAMEE => array( 1, 'FULLPAGENAMEE' ),
242 MAG_SUBPAGENAME => array( 1, 'SUBPAGENAME' ),
243 MAG_SUBPAGENAMEE => array( 1, 'SUBPAGENAMEE' ),
244 MAG_TALKPAGENAME => array( 1, 'TALKPAGENAME' ),
245 MAG_TALKPAGENAMEE => array( 1, 'TALKPAGENAMEE' ),
246 MAG_SUBJECTPAGENAME => array( 1, 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ),
247 MAG_SUBJECTPAGENAMEE => array( 1, 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ),
248 MAG_MSG => array( 0, 'MSG:' ),
249 MAG_SUBST => array( 0, 'SUBST:' ),
250 MAG_MSGNW => array( 0, 'MSGNW:' ),
251 MAG_END => array( 0, '__END__' ),
252 MAG_IMG_THUMBNAIL => array( 1, 'thumbnail', 'thumb' ),
253 MAG_IMG_MANUALTHUMB => array( 1, 'thumbnail=$1', 'thumb=$1'),
254 MAG_IMG_RIGHT => array( 1, 'right' ),
255 MAG_IMG_LEFT => array( 1, 'left' ),
256 MAG_IMG_NONE => array( 1, 'none' ),
257 MAG_IMG_WIDTH => array( 1, '$1px' ),
258 MAG_IMG_CENTER => array( 1, 'center', 'centre' ),
259 MAG_IMG_FRAMED => array( 1, 'framed', 'enframed', 'frame' ),
260 MAG_INT => array( 0, 'INT:' ),
261 MAG_SITENAME => array( 1, 'SITENAME' ),
262 MAG_NS => array( 0, 'NS:' ),
263 MAG_LOCALURL => array( 0, 'LOCALURL:' ),
264 MAG_LOCALURLE => array( 0, 'LOCALURLE:' ),
265 MAG_SERVER => array( 0, 'SERVER' ),
266 MAG_SERVERNAME => array( 0, 'SERVERNAME' ),
267 MAG_SCRIPTPATH => array( 0, 'SCRIPTPATH' ),
268 MAG_GRAMMAR => array( 0, 'GRAMMAR:' ),
269 MAG_NOTITLECONVERT => array( 0, '__NOTITLECONVERT__', '__NOTC__'),
270 MAG_NOCONTENTCONVERT => array( 0, '__NOCONTENTCONVERT__', '__NOCC__'),
271 MAG_CURRENTWEEK => array( 1, 'CURRENTWEEK' ),
272 MAG_CURRENTDOW => array( 1, 'CURRENTDOW' ),
273 MAG_REVISIONID => array( 1, 'REVISIONID' ),
274 MAG_PLURAL => array( 0, 'PLURAL:' ),
275 MAG_FULLURL => array( 0, 'FULLURL:' ),
276 MAG_FULLURLE => array( 0, 'FULLURLE:' ),
277 MAG_LCFIRST => array( 0, 'LCFIRST:' ),
278 MAG_UCFIRST => array( 0, 'UCFIRST:' ),
279 MAG_LC => array( 0, 'LC:' ),
280 MAG_UC => array( 0, 'UC:' ),
281 MAG_RAW => array( 0, 'RAW:' ),
282 MAG_DISPLAYTITLE => array( 1, 'DISPLAYTITLE' ),
283 MAG_RAWSUFFIX => array( 1, 'R' ),
284 MAG_NEWSECTIONLINK => array( 1, '__NEWSECTIONLINK__' ),
287 if (!$wgCachedMessageArrays) {
288 require_once('Messages.php');
291 /* a fake language converter */
292 class fakeConverter {
293 var $mLang;
294 function fakeConverter($langobj) {$this->mLang = $langobj;}
295 function convert($t, $i) {return $t;}
296 function parserConvert($t, $p) {return $t;}
297 function getVariants() { return array( $this->mLang->getCode() ); }
298 function getPreferredVariant() {return $this->mLang->getCode(); }
299 function findVariantLink(&$l, &$n) {}
300 function getExtraHashOptions() {return '';}
301 function getParsedTitle() {return '';}
302 function markNoConversion($text) {return $text;}
303 function convertCategoryKey( $key ) {return $key; }
307 #--------------------------------------------------------------------------
308 # Internationalisation code
309 #--------------------------------------------------------------------------
311 class Language {
312 var $mConverter;
313 function Language() {
315 # Copies any missing values in the specified arrays from En to the current language
316 $fillin = array( 'wgSysopSpecialPages', 'wgValidSpecialPages', 'wgDeveloperSpecialPages' );
317 $name = get_class( $this );
319 if( strpos( $name, 'language' ) == 0){
320 $lang = ucfirst( substr( $name, 8 ) );
321 foreach( $fillin as $arrname ){
322 $langver = "{$arrname}{$lang}";
323 $enver = "{$arrname}En";
324 if( ! isset( $GLOBALS[$langver] ) || ! isset( $GLOBALS[$enver] ))
325 continue;
326 foreach($GLOBALS[$enver] as $spage => $text){
327 if( ! isset( $GLOBALS[$langver][$spage] ) )
328 $GLOBALS[$langver][$spage] = $text;
332 $this->mConverter = new fakeConverter($this);
336 * Exports the default user options as defined in
337 * $wgDefaultUserOptionsEn, user preferences can override some of these
338 * depending on what's in (Local|Default)Settings.php and some defines.
340 * @return array
342 function getDefaultUserOptions() {
343 global $wgDefaultUserOptionsEn ;
344 return $wgDefaultUserOptionsEn ;
348 * Exports $wgBookstoreListEn
349 * @return array
351 function getBookstoreList() {
352 global $wgBookstoreListEn ;
353 return $wgBookstoreListEn ;
357 * @return array
359 function getNamespaces() {
360 global $wgNamespaceNamesEn;
361 return $wgNamespaceNamesEn;
365 * A convenience function that returns the same thing as
366 * getNamespaces() except with the array values changed to ' '
367 * where it found '_', useful for producing output to be displayed
368 * e.g. in <select> forms.
370 * @return array
372 function getFormattedNamespaces() {
373 $ns = $this->getNamespaces();
374 foreach($ns as $k => $v) {
375 $ns[$k] = strtr($v, '_', ' ');
377 return $ns;
381 * Get a namespace value by key
382 * <code>
383 * $mw_ns = $wgContLang->getNsText( NS_MEDIAWIKI );
384 * echo $mw_ns; // prints 'MediaWiki'
385 * </code>
387 * @param int $index the array key of the namespace to return
388 * @return mixed, string if the namespace value exists, otherwise false
390 function getNsText( $index ) {
391 $ns = $this->getNamespaces();
392 return isset( $ns[$index] ) ? $ns[$index] : false;
396 * A convenience function that returns the same thing as
397 * getNsText() except with '_' changed to ' ', useful for
398 * producing output.
400 * @return array
402 function getFormattedNsText( $index ) {
403 $ns = $this->getNsText( $index );
404 return strtr($ns, '_', ' ');
408 * Get a namespace key by value, case insensetive.
410 * @param string $text
411 * @return mixed An integer if $text is a valid value otherwise false
413 function getNsIndex( $text ) {
414 $ns = $this->getNamespaces();
416 foreach ( $ns as $i => $n ) {
417 if ( strcasecmp( $n, $text ) == 0)
418 return $i;
420 return false;
424 * short names for language variants used for language conversion links.
426 * @param string $code
427 * @return string
429 function getVariantname( $code ) {
430 return wfMsg( "variantname-$code" );
433 function specialPage( $name ) {
434 return $this->getNsText(NS_SPECIAL) . ':' . $name;
437 function getQuickbarSettings() {
438 global $wgQuickbarSettingsEn;
439 return $wgQuickbarSettingsEn;
442 function getSkinNames() {
443 global $wgSkinNamesEn;
444 return $wgSkinNamesEn;
447 function getMathNames() {
448 global $wgMathNamesEn;
449 return $wgMathNamesEn;
452 function getDateFormats() {
453 global $wgDateFormatsEn;
454 return $wgDateFormatsEn;
457 function getUserToggles() {
458 global $wgUserTogglesEn;
459 return $wgUserTogglesEn;
462 function getUserToggle( $tog ) {
463 return wfMsg( "tog-$tog" );
466 function getLanguageNames() {
467 global $wgLanguageNamesEn;
468 return $wgLanguageNamesEn;
471 function getLanguageName( $code ) {
472 global $wgLanguageNamesEn;
473 if ( ! array_key_exists( $code, $wgLanguageNamesEn ) ) {
474 return '';
476 return $wgLanguageNamesEn[$code];
479 function getMonthName( $key ) {
480 global $wgMonthNamesEn, $wgContLang;
481 // see who called us and use the correct message function
482 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
483 return wfMsgForContent($wgMonthNamesEn[$key-1]);
484 else
485 return wfMsg($wgMonthNamesEn[$key-1]);
488 /* by default we just return base form */
489 function getMonthNameGen( $key ) {
490 return $this->getMonthName( $key );
493 function getMonthAbbreviation( $key ) {
494 global $wgMonthAbbreviationsEn, $wgContLang;
495 // see who called us and use the correct message function
496 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
497 return wfMsgForContent(@$wgMonthAbbreviationsEn[$key-1]);
498 else
499 return wfMsg(@$wgMonthAbbreviationsEn[$key-1]);
502 function getWeekdayName( $key ) {
503 global $wgWeekdayNamesEn, $wgContLang;
504 // see who called us and use the correct message function
505 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
506 return wfMsgForContent($wgWeekdayNamesEn[$key-1]);
507 else
508 return wfMsg($wgWeekdayNamesEn[$key-1]);
512 * Used by date() and time() to adjust the time output.
513 * @public
514 * @param int $ts the time in date('YmdHis') format
515 * @param mixed $tz adjust the time by this amount (default false,
516 * mean we get user timecorrection setting)
517 * @return int
520 function userAdjust( $ts, $tz = false ) {
521 global $wgUser, $wgLocalTZoffset;
523 if (!$tz) {
524 $tz = $wgUser->getOption( 'timecorrection' );
527 # minutes and hours differences:
528 $minDiff = 0;
529 $hrDiff = 0;
531 if ( $tz === '' ) {
532 # Global offset in minutes.
533 if( isset($wgLocalTZoffset) ) {
534 $hrDiff = $wgLocalTZoffset % 60;
535 $minDiff = $wgLocalTZoffset - ($hrDiff * 60);
537 } elseif ( strpos( $tz, ':' ) !== false ) {
538 $tzArray = explode( ':', $tz );
539 $hrDiff = intval($tzArray[0]);
540 $minDiff = intval($hrDiff < 0 ? -$tzArray[1] : $tzArray[1]);
541 } else {
542 $hrDiff = intval( $tz );
545 # No difference ? Return time unchanged
546 if ( 0 == $hrDiff && 0 == $minDiff ) { return $ts; }
548 # Generate an adjusted date
549 $t = mktime( (
550 (int)substr( $ts, 8, 2) ) + $hrDiff, # Hours
551 (int)substr( $ts, 10, 2 ) + $minDiff, # Minutes
552 (int)substr( $ts, 12, 2 ), # Seconds
553 (int)substr( $ts, 4, 2 ), # Month
554 (int)substr( $ts, 6, 2 ), # Day
555 (int)substr( $ts, 0, 4 ) ); #Year
556 return date( 'YmdHis', $t );
560 * This is meant to be used by time(), date(), and timeanddate() to get
561 * the date preference they're supposed to use, it should be used in
562 * all children.
564 *<code>
565 * function timeanddate([...], $format = true) {
566 * $datePreference = $this->dateFormat($format);
567 * [...]
568 *</code>
570 * @param mixed $usePrefs: if true, the user's preference is used
571 * if false, the site/language default is used
572 * if int/string, assumed to be a format.
573 * @return string
575 function dateFormat( $usePrefs = true ) {
576 global $wgUser;
578 if( is_bool( $usePrefs ) ) {
579 if( $usePrefs ) {
580 $datePreference = $wgUser->getOption( 'date' );
581 } else {
582 $options = $this->getDefaultUserOptions();
583 $datePreference = (string)$options['date'];
585 } else {
586 $datePreference = (string)$usePrefs;
589 // return int
590 if( $datePreference == '' ) {
591 return MW_DATE_DEFAULT;
594 return $datePreference;
598 * @public
599 * @param mixed $ts the time format which needs to be turned into a
600 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
601 * @param bool $adj whether to adjust the time output according to the
602 * user configured offset ($timecorrection)
603 * @param mixed $format true to use user's date format preference
604 * @param string $timecorrection the time offset as returned by
605 * validateTimeZone() in Special:Preferences
606 * @return string
608 function date( $ts, $adj = false, $format = true, $timecorrection = false ) {
609 global $wgUser, $wgAmericanDates;
611 if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
613 $datePreference = $this->dateFormat( $format );
614 if( $datePreference == MW_DATE_DEFAULT ) {
615 $datePreference = $wgAmericanDates ? MW_DATE_MDY : MW_DATE_DMY;
618 $month = $this->formatMonth( substr( $ts, 4, 2 ), $datePreference );
619 $day = $this->formatDay( substr( $ts, 6, 2 ), $datePreference );
620 $year = $this->formatNum( substr( $ts, 0, 4 ), true );
622 switch( $datePreference ) {
623 case MW_DATE_DMY: return "$day $month $year";
624 case MW_DATE_YMD: return "$year $month $day";
625 case MW_DATE_ISO: return substr($ts, 0, 4). '-' . substr($ts, 4, 2). '-' .substr($ts, 6, 2);
626 default: return "$month $day, $year";
631 * @public
632 * @param mixed $ts the time format which needs to be turned into a
633 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
634 * @param bool $adj whether to adjust the time output according to the
635 * user configured offset ($timecorrection)
636 * @param mixed $format true to use user's date format preference
637 * @param string $timecorrection the time offset as returned by
638 * validateTimeZone() in Special:Preferences
639 * @return string
641 function time( $ts, $adj = false, $format = true, $timecorrection = false ) {
642 global $wgUser;
644 if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
645 $datePreference = $this->dateFormat( $format );
647 $sep = $this->timeSeparator( $format );
649 $hh = substr( $ts, 8, 2 );
650 $mm = substr( $ts, 10, 2 );
651 $ss = substr( $ts, 12, 2 );
653 if ( $datePreference != MW_DATE_ISO ) {
654 $hh = $this->formatNum( $hh, true );
655 $mm = $this->formatNum( $mm, true );
656 //$ss = $this->formatNum( $ss, true );
657 return $hh . $sep . $mm;
658 } else {
659 return $hh . ':' . $mm . ':' . $ss;
664 * Default separator character between hours, minutes, and seconds.
665 * Will be used by Language::time() for non-ISO formats.
666 * (ISO will always use a colon.)
667 * @return string
669 function timeSeparator( $format ) {
670 return ':';
674 * String to insert between the time and the date in a combined
675 * string. Should include any relevant whitespace.
676 * @return string
678 function timeDateSeparator( $format ) {
679 return ', ';
683 * Return true if the time should display before the date.
684 * @return bool
685 * @private
687 function timeBeforeDate() {
688 return true;
691 function formatMonth( $month, $format ) {
692 return $this->getMonthName( $month );
695 function formatDay( $day, $format ) {
696 return $this->formatNum( 0 + $day, true );
700 * @public
701 * @param mixed $ts the time format which needs to be turned into a
702 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
703 * @param bool $adj whether to adjust the time output according to the
704 * user configured offset ($timecorrection)
706 * @param mixed $format what format to return, if it's false output the
707 * default one (default true)
708 * @param string $timecorrection the time offset as returned by
709 * validateTimeZone() in Special:Preferences
710 * @return string
712 function timeanddate( $ts, $adj = false, $format = true, $timecorrection = false) {
713 global $wgUser;
715 $datePreference = $this->dateFormat($format);
716 switch ( $datePreference ) {
717 case MW_DATE_ISO: return $this->date( $ts, $adj, $format, $timecorrection ) . ' ' .
718 $this->time( $ts, $adj, $format, $timecorrection );
719 default:
720 $time = $this->time( $ts, $adj, $format, $timecorrection );
721 $sep = $this->timeDateSeparator( $datePreference );
722 $date = $this->date( $ts, $adj, $format, $timecorrection );
723 return $this->timeBeforeDate( $datePreference )
724 ? $time . $sep . $date
725 : $date . $sep . $time;
729 function getMessage( $key ) {
730 global $wgAllMessagesEn;
731 return @$wgAllMessagesEn[$key];
734 function getAllMessages() {
735 global $wgAllMessagesEn;
736 return $wgAllMessagesEn;
739 function iconv( $in, $out, $string ) {
740 # For most languages, this is a wrapper for iconv
741 return iconv( $in, $out, $string );
744 function ucfirst( $string ) {
745 # For most languages, this is a wrapper for ucfirst()
746 return ucfirst( $string );
749 function uc( $str ) {
750 return strtoupper( $str );
753 function lcfirst( $s ) {
754 return strtolower( $s{0} ). substr( $s, 1 );
757 function lc( $str ) {
758 return strtolower( $str );
761 function checkTitleEncoding( $s ) {
762 global $wgInputEncoding;
764 # Check for UTF-8 URLs; Internet Explorer produces these if you
765 # type non-ASCII chars in the URL bar or follow unescaped links.
766 $ishigh = preg_match( '/[\x80-\xff]/', $s);
767 $isutf = ($ishigh ? preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
768 '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s ) : true );
770 if( ($wgInputEncoding != 'utf-8') and $ishigh and $isutf )
771 return @iconv( 'UTF-8', $wgInputEncoding, $s );
773 if( ($wgInputEncoding == 'utf-8') and $ishigh and !$isutf )
774 return utf8_encode( $s );
776 # Other languages can safely leave this function, or replace
777 # it with one to detect and convert another legacy encoding.
778 return $s;
782 * Some languages have special punctuation to strip out
783 * or characters which need to be converted for MySQL's
784 * indexing to grok it correctly. Make such changes here.
786 * @param string $in
787 * @return string
789 function stripForSearch( $in ) {
790 return strtolower( $in );
793 function convertForSearchResult( $termsArray ) {
794 # some languages, e.g. Chinese, need to do a conversion
795 # in order for search results to be displayed correctly
796 return $termsArray;
800 * Get the first character of a string. In ASCII, return
801 * first byte of the string. UTF8 and others have to
802 * overload this.
804 * @param string $s
805 * @return string
807 function firstChar( $s ) {
808 return $s[0];
811 function initEncoding() {
812 # Some languages may have an alternate char encoding option
813 # (Esperanto X-coding, Japanese furigana conversion, etc)
814 # If this language is used as the primary content language,
815 # an override to the defaults can be set here on startup.
816 #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
819 function setAltEncoding() {
820 # Some languages may have an alternate char encoding option
821 # (Esperanto X-coding, Japanese furigana conversion, etc)
822 # If 'altencoding' is checked in user prefs, this gives a
823 # chance to swap out the default encoding settings.
824 #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
827 function recodeForEdit( $s ) {
828 # For some languages we'll want to explicitly specify
829 # which characters make it into the edit box raw
830 # or are converted in some way or another.
831 # Note that if wgOutputEncoding is different from
832 # wgInputEncoding, this text will be further converted
833 # to wgOutputEncoding.
834 global $wgInputEncoding, $wgEditEncoding;
835 if( $wgEditEncoding == '' or
836 $wgEditEncoding == $wgInputEncoding ) {
837 return $s;
838 } else {
839 return $this->iconv( $wgInputEncoding, $wgEditEncoding, $s );
843 function recodeInput( $s ) {
844 # Take the previous into account.
845 global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
846 if($wgEditEncoding != "") {
847 $enc = $wgEditEncoding;
848 } else {
849 $enc = $wgOutputEncoding;
851 if( $enc == $wgInputEncoding ) {
852 return $s;
853 } else {
854 return $this->iconv( $enc, $wgInputEncoding, $s );
859 * For right-to-left language support
861 * @return bool
863 function isRTL() { return false; }
864 function getDirMark() { return $this->isRTL() ? '&rlm;' : '&lrm;'; }
867 * To allow "foo[[bar]]" to extend the link over the whole word "foobar"
869 * @return bool
871 function linkPrefixExtension() { return false; }
874 function &getMagicWords() {
875 global $wgMagicWordsEn;
876 return $wgMagicWordsEn;
879 # Fill a MagicWord object with data from here
880 function getMagic( &$mw ) {
881 $raw = $this->getMagicWords();
883 wfRunHooks( 'LanguageGetMagic', array( &$raw ) );
885 if( !isset( $raw[$mw->mId] ) ) {
886 # Fall back to English if local list is incomplete
887 $raw =& Language::getMagicWords();
889 $rawEntry = $raw[$mw->mId];
890 $mw->mCaseSensitive = $rawEntry[0];
891 $mw->mSynonyms = array_slice( $rawEntry, 1 );
895 * Italic is unsuitable for some languages
897 * @public
899 * @param string $text The text to be emphasized.
900 * @return string
902 function emphasize( $text ) {
903 return "<em>$text</em>";
907 * Normally we output all numbers in plain en_US style, that is
908 * 293,291.235 for twohundredninetythreethousand-twohundredninetyone
909 * point twohundredthirtyfive. However this is not sutable for all
910 * languages, some such as Pakaran want ੨੯੩,੨੯੫.੨੩੫ and others such as
911 * Icelandic just want to use commas instead of dots, and dots instead
912 * of commas like "293.291,235".
914 * An example of this function being called:
915 * <code>
916 * wfMsg( 'message', $wgLang->formatNum( $num ) )
917 * </code>
919 * See LanguageGu.php for the Gujarati implementation and
920 * LanguageIs.php for the , => . and . => , implementation.
922 * @todo check if it's viable to use localeconv() for the decimal
923 * seperator thing.
924 * @public
925 * @param mixed $number the string to be formatted, should be an integer or
926 * a floating point number.
927 * @param bool $nocommafy Set to true for special numbers like dates
928 * @return string
930 function formatNum( $number, $nocommafy = false ) {
931 global $wgTranslateNumerals;
932 if (!$nocommafy) {
933 $number = $this->commafy($number);
934 $s = $this->separatorTransformTable();
935 if (!is_null($s)) { $number = strtr($number, $s); }
938 if ($wgTranslateNumerals) {
939 $s = $this->digitTransformTable();
940 if (!is_null($s)) { $number = strtr($number, $s); }
943 return $number;
947 * Adds commas to a given number
949 * @param mixed $_
950 * @return string
952 function commafy($_) {
953 return strrev((string)preg_replace('/(\d{3})(?=\d)(?!\d*\.)/','$1,',strrev($_)));
956 function digitTransformTable() {
957 return null;
960 function separatorTransformTable() {
961 return null;
966 * For the credit list in includes/Credits.php (action=credits)
968 * @param array $l
969 * @return string
971 function listToText( $l ) {
972 $s = '';
973 $m = count($l) - 1;
974 for ($i = $m; $i >= 0; $i--) {
975 if ($i == $m) {
976 $s = $l[$i];
977 } else if ($i == $m - 1) {
978 $s = $l[$i] . ' ' . wfMsg('and') . ' ' . $s;
979 } else {
980 $s = $l[$i] . ', ' . $s;
983 return $s;
986 # Crop a string from the beginning or end to a certain number of bytes.
987 # (Bytes are used because our storage has limited byte lengths for some
988 # columns in the database.) Multibyte charsets will need to make sure that
989 # only whole characters are included!
991 # $length does not include the optional ellipsis.
992 # If $length is negative, snip from the beginning
993 function truncate( $string, $length, $ellipsis = '' ) {
994 if( $length == 0 ) {
995 return $ellipsis;
997 if ( strlen( $string ) <= abs( $length ) ) {
998 return $string;
1000 if( $length > 0 ) {
1001 $string = substr( $string, 0, $length );
1002 return $string . $ellipsis;
1003 } else {
1004 $string = substr( $string, $length );
1005 return $ellipsis . $string;
1010 * Grammatical transformations, needed for inflected languages
1011 * Invoked by putting {{grammar:case|word}} in a message
1013 * @param string $word
1014 * @param string $case
1015 * @return string
1017 function convertGrammar( $word, $case ) {
1018 return $word;
1022 * Plural form transformations, needed for some languages.
1023 * For example, where are 3 form of plural in Russian and Polish,
1024 * depending on "count mod 10". See [[w:Plural]]
1025 * For English it is pretty simple.
1027 * Invoked by putting {{plural:count|wordform1|wordform2}}
1028 * or {{plural:count|wordform1|wordform2|wordform3}}
1030 * Example: {{plural:{{NUMBEROFARTICLES}}|article|articles}}
1032 * @param integer $count
1033 * @param string $wordform1
1034 * @param string $wordform2
1035 * @param string $wordform3 (optional)
1036 * @return string
1038 function convertPlural( $count, $wordform1, $wordform2, $wordform3) {
1039 return $count == '1' ? $wordform1 : $wordform2;
1043 * For translaing of expiry times
1044 * @param string The validated block time in English
1045 * @return Somehow translated block time
1046 * @see LanguageFi.php for example implementation
1048 function translateBlockExpiry( $str ) {
1050 $scBlockExpiryOptions = wfMsg( 'ipboptions' );
1052 if ( $scBlockExpiryOptions == '-') {
1053 return $str;
1056 foreach (explode(',', $scBlockExpiryOptions) as $option) {
1057 if ( strpos($option, ":") === false )
1058 continue;
1059 list($show, $value) = explode(":", $option);
1060 if ( strcmp ( $str, $value) == 0 )
1061 return '<span title="' . htmlspecialchars($str). '">' .
1062 htmlspecialchars( trim( $show ) ) . '</span>';
1065 return $str;
1069 * languages like Chinese need to be segmented in order for the diff
1070 * to be of any use
1072 * @param string $text
1073 * @return string
1075 function segmentForDiff( $text ) {
1076 return $text;
1080 * and unsegment to show the result
1082 * @param string $text
1083 * @return string
1085 function unsegmentForDiff( $text ) {
1086 return $text;
1089 # convert text to different variants of a language.
1090 function convert( $text, $isTitle = false) {
1091 return $this->mConverter->convert($text, $isTitle);
1094 # Convert text from within Parser
1095 function parserConvert( $text, &$parser ) {
1096 return $this->mConverter->parserConvert( $text, $parser );
1100 * Perform output conversion on a string, and encode for safe HTML output.
1101 * @param string $text
1102 * @param bool $isTitle -- wtf?
1103 * @return string
1104 * @todo this should get integrated somewhere sane
1106 function convertHtml( $text, $isTitle = false ) {
1107 return htmlspecialchars( $this->convert( $text, $isTitle ) );
1110 function convertCategoryKey( $key ) {
1111 return $this->mConverter->convertCategoryKey( $key );
1115 * get the list of variants supported by this langauge
1116 * see sample implementation in LanguageZh.php
1118 * @return array an array of language codes
1120 function getVariants() {
1121 return $this->mConverter->getVariants();
1125 function getPreferredVariant() {
1126 return $this->mConverter->getPreferredVariant();
1130 * if a language supports multiple variants, it is
1131 * possible that non-existing link in one variant
1132 * actually exists in another variant. this function
1133 * tries to find it. See e.g. LanguageZh.php
1135 * @param string $link the name of the link
1136 * @param mixed $nt the title object of the link
1137 * @return null the input parameters may be modified upon return
1139 function findVariantLink( &$link, &$nt ) {
1140 $this->mConverter->findVariantLink($link, $nt);
1144 * returns language specific options used by User::getPageRenderHash()
1145 * for example, the preferred language variant
1147 * @return string
1148 * @public
1150 function getExtraHashOptions() {
1151 return $this->mConverter->getExtraHashOptions();
1155 * for languages that support multiple variants, the title of an
1156 * article may be displayed differently in different variants. this
1157 * function returns the apporiate title defined in the body of the article.
1159 * @return string
1161 function getParsedTitle() {
1162 return $this->mConverter->getParsedTitle();
1166 * Enclose a string with the "no conversion" tag. This is used by
1167 * various functions in the Parser
1169 * @param string $text text to be tagged for no conversion
1170 * @return string the tagged text
1172 function markNoConversion( $text ) {
1173 return $this->mConverter->markNoConversion( $text );
1177 * A regular expression to match legal word-trailing characters
1178 * which should be merged onto a link of the form [[foo]]bar.
1180 * @return string
1181 * @public
1183 function linkTrail() {
1184 return $this->getMessage( 'linktrail' );
1187 function getLangObj() {
1188 return $this;
1192 * Get the RFC 3066 code for this language object
1194 function getCode() {
1195 return str_replace( '_', '-', strtolower( substr( get_class( $this ), 8 ) ) );
1201 # FIXME: Merge all UTF-8 support code into Language base class.
1202 # We no longer support Latin-1 charset.
1203 require_once( 'LanguageUtf8.php' );
1205 # This should fail gracefully if there's not a localization available
1206 wfSuppressWarnings();
1207 // Preload base classes to work around APC/PHP5 bug
1208 include_once( 'Language' . str_replace( '-', '_', ucfirst( $wgLanguageCode ) ) . '.deps.php' );
1209 include_once( 'Language' . str_replace( '-', '_', ucfirst( $wgLanguageCode ) ) . '.php' );
1210 wfRestoreWarnings();