* Update to Catalan translation (ca)
[mediawiki.git] / languages / Language.php
blobcbb5e31655ca9afa6de459d25b72a7c24aa78d76
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_NOGALLERY => array( 0, '__NOGALLERY__' ),
217 MAG_FORCETOC => array( 0, '__FORCETOC__' ),
218 MAG_TOC => array( 0, '__TOC__' ),
219 MAG_NOEDITSECTION => array( 0, '__NOEDITSECTION__' ),
220 MAG_START => array( 0, '__START__' ),
221 MAG_CURRENTMONTH => array( 1, 'CURRENTMONTH' ),
222 MAG_CURRENTMONTHNAME => array( 1, 'CURRENTMONTHNAME' ),
223 MAG_CURRENTMONTHNAMEGEN => array( 1, 'CURRENTMONTHNAMEGEN' ),
224 MAG_CURRENTMONTHABBREV => array( 1, 'CURRENTMONTHABBREV' ),
225 MAG_CURRENTDAY => array( 1, 'CURRENTDAY' ),
226 MAG_CURRENTDAY2 => array( 1, 'CURRENTDAY2' ),
227 MAG_CURRENTDAYNAME => array( 1, 'CURRENTDAYNAME' ),
228 MAG_CURRENTYEAR => array( 1, 'CURRENTYEAR' ),
229 MAG_CURRENTTIME => array( 1, 'CURRENTTIME' ),
230 MAG_NUMBEROFPAGES => array( 1, 'NUMBEROFPAGES' ),
231 MAG_NUMBEROFARTICLES => array( 1, 'NUMBEROFARTICLES' ),
232 MAG_NUMBEROFFILES => array( 1, 'NUMBEROFFILES' ),
233 MAG_NUMBEROFUSERS => array( 1, 'NUMBEROFUSERS' ),
234 MAG_PAGENAME => array( 1, 'PAGENAME' ),
235 MAG_PAGENAMEE => array( 1, 'PAGENAMEE' ),
236 MAG_NAMESPACE => array( 1, 'NAMESPACE' ),
237 MAG_NAMESPACEE => array( 1, 'NAMESPACEE' ),
238 MAG_TALKSPACE => array( 1, 'TALKSPACE' ),
239 MAG_TALKSPACEE => array( 1, 'TALKSPACEE' ),
240 MAG_SUBJECTSPACE => array( 1, 'SUBJECTSPACE', 'ARTICLESPACE' ),
241 MAG_SUBJECTSPACEE => array( 1, 'SUBJECTSPACEE', 'ARTICLESPACEE' ),
242 MAG_FULLPAGENAME => array( 1, 'FULLPAGENAME' ),
243 MAG_FULLPAGENAMEE => array( 1, 'FULLPAGENAMEE' ),
244 MAG_SUBPAGENAME => array( 1, 'SUBPAGENAME' ),
245 MAG_SUBPAGENAMEE => array( 1, 'SUBPAGENAMEE' ),
246 MAG_BASEPAGENAME => array( 1, 'BASEPAGENAME' ),
247 MAG_BASEPAGENAMEE => array( 1, 'BASEPAGENAMEE' ),
248 MAG_TALKPAGENAME => array( 1, 'TALKPAGENAME' ),
249 MAG_TALKPAGENAMEE => array( 1, 'TALKPAGENAMEE' ),
250 MAG_SUBJECTPAGENAME => array( 1, 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ),
251 MAG_SUBJECTPAGENAMEE => array( 1, 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ),
252 MAG_MSG => array( 0, 'MSG:' ),
253 MAG_SUBST => array( 0, 'SUBST:' ),
254 MAG_MSGNW => array( 0, 'MSGNW:' ),
255 MAG_END => array( 0, '__END__' ),
256 MAG_IMG_THUMBNAIL => array( 1, 'thumbnail', 'thumb' ),
257 MAG_IMG_MANUALTHUMB => array( 1, 'thumbnail=$1', 'thumb=$1'),
258 MAG_IMG_RIGHT => array( 1, 'right' ),
259 MAG_IMG_LEFT => array( 1, 'left' ),
260 MAG_IMG_NONE => array( 1, 'none' ),
261 MAG_IMG_WIDTH => array( 1, '$1px' ),
262 MAG_IMG_CENTER => array( 1, 'center', 'centre' ),
263 MAG_IMG_FRAMED => array( 1, 'framed', 'enframed', 'frame' ),
264 MAG_INT => array( 0, 'INT:' ),
265 MAG_SITENAME => array( 1, 'SITENAME' ),
266 MAG_NS => array( 0, 'NS:' ),
267 MAG_LOCALURL => array( 0, 'LOCALURL:' ),
268 MAG_LOCALURLE => array( 0, 'LOCALURLE:' ),
269 MAG_SERVER => array( 0, 'SERVER' ),
270 MAG_SERVERNAME => array( 0, 'SERVERNAME' ),
271 MAG_SCRIPTPATH => array( 0, 'SCRIPTPATH' ),
272 MAG_GRAMMAR => array( 0, 'GRAMMAR:' ),
273 MAG_NOTITLECONVERT => array( 0, '__NOTITLECONVERT__', '__NOTC__'),
274 MAG_NOCONTENTCONVERT => array( 0, '__NOCONTENTCONVERT__', '__NOCC__'),
275 MAG_CURRENTWEEK => array( 1, 'CURRENTWEEK' ),
276 MAG_CURRENTDOW => array( 1, 'CURRENTDOW' ),
277 MAG_REVISIONID => array( 1, 'REVISIONID' ),
278 MAG_PLURAL => array( 0, 'PLURAL:' ),
279 MAG_FULLURL => array( 0, 'FULLURL:' ),
280 MAG_FULLURLE => array( 0, 'FULLURLE:' ),
281 MAG_LCFIRST => array( 0, 'LCFIRST:' ),
282 MAG_UCFIRST => array( 0, 'UCFIRST:' ),
283 MAG_LC => array( 0, 'LC:' ),
284 MAG_UC => array( 0, 'UC:' ),
285 MAG_RAW => array( 0, 'RAW:' ),
286 MAG_DISPLAYTITLE => array( 1, 'DISPLAYTITLE' ),
287 MAG_RAWSUFFIX => array( 1, 'R' ),
288 MAG_NEWSECTIONLINK => array( 1, '__NEWSECTIONLINK__' ),
289 MAG_CURRENTVERSION => array( 1, 'CURRENTVERSION' ),
290 MAG_URLENCODE => array( 0, 'URLENCODE:' ),
291 MAG_CURRENTTIMESTAMP => array( 1, 'CURRENTTIMESTAMP' ),
292 MAG_DIRECTIONMARK => array( 1, 'DIRECTIONMARK', 'DIRMARK' ),
293 MAG_LANGUAGE => array( 0, '#LANGUAGE:' ),
294 MAG_CONTENTLANGUAGE => array( 1, 'CONTENTLANGUAGE', 'CONTENTLANG' ),
295 MAG_PAGESINNAMESPACE => array( 1, 'PAGESINNAMESPACE:', 'PAGESINNS:' ),
296 MAG_NUMBEROFADMINS => array( 1, 'NUMBEROFADMINS' ),
297 MAG_FORMATNUM => array( 0, 'FORMATNUM' ),
301 if (!$wgCachedMessageArrays) {
302 require_once('Messages.php');
305 /* a fake language converter */
306 class fakeConverter {
307 var $mLang;
308 function fakeConverter($langobj) {$this->mLang = $langobj;}
309 function convert($t, $i) {return $t;}
310 function parserConvert($t, $p) {return $t;}
311 function getVariants() { return array( $this->mLang->getCode() ); }
312 function getPreferredVariant() {return $this->mLang->getCode(); }
313 function findVariantLink(&$l, &$n) {}
314 function getExtraHashOptions() {return '';}
315 function getParsedTitle() {return '';}
316 function markNoConversion($text) {return $text;}
317 function convertCategoryKey( $key ) {return $key; }
321 #--------------------------------------------------------------------------
322 # Internationalisation code
323 #--------------------------------------------------------------------------
325 class Language {
326 var $mConverter;
327 function __construct() {
328 $this->mConverter = new fakeConverter($this);
332 * Exports the default user options as defined in
333 * $wgDefaultUserOptionsEn, user preferences can override some of these
334 * depending on what's in (Local|Default)Settings.php and some defines.
336 * @return array
338 function getDefaultUserOptions() {
339 global $wgDefaultUserOptionsEn;
340 return $wgDefaultUserOptionsEn;
344 * Exports $wgBookstoreListEn
345 * @return array
347 function getBookstoreList() {
348 global $wgBookstoreListEn;
349 return $wgBookstoreListEn;
353 * @return array
355 function getNamespaces() {
356 global $wgNamespaceNamesEn;
357 return $wgNamespaceNamesEn;
361 * A convenience function that returns the same thing as
362 * getNamespaces() except with the array values changed to ' '
363 * where it found '_', useful for producing output to be displayed
364 * e.g. in <select> forms.
366 * @return array
368 function getFormattedNamespaces() {
369 $ns = $this->getNamespaces();
370 foreach($ns as $k => $v) {
371 $ns[$k] = strtr($v, '_', ' ');
373 return $ns;
377 * Get a namespace value by key
378 * <code>
379 * $mw_ns = $wgContLang->getNsText( NS_MEDIAWIKI );
380 * echo $mw_ns; // prints 'MediaWiki'
381 * </code>
383 * @param int $index the array key of the namespace to return
384 * @return mixed, string if the namespace value exists, otherwise false
386 function getNsText( $index ) {
387 $ns = $this->getNamespaces();
388 return isset( $ns[$index] ) ? $ns[$index] : false;
392 * A convenience function that returns the same thing as
393 * getNsText() except with '_' changed to ' ', useful for
394 * producing output.
396 * @return array
398 function getFormattedNsText( $index ) {
399 $ns = $this->getNsText( $index );
400 return strtr($ns, '_', ' ');
404 * Get a namespace key by value, case insensetive.
406 * @param string $text
407 * @return mixed An integer if $text is a valid value otherwise false
409 function getNsIndex( $text ) {
410 $ns = $this->getNamespaces();
412 foreach ( $ns as $i => $n ) {
413 if ( strcasecmp( $n, $text ) == 0)
414 return $i;
416 return false;
420 * short names for language variants used for language conversion links.
422 * @param string $code
423 * @return string
425 function getVariantname( $code ) {
426 return wfMsg( "variantname-$code" );
429 function specialPage( $name ) {
430 return $this->getNsText(NS_SPECIAL) . ':' . $name;
433 function getQuickbarSettings() {
434 global $wgQuickbarSettingsEn;
435 return $wgQuickbarSettingsEn;
438 function getSkinNames() {
439 global $wgSkinNamesEn;
440 return $wgSkinNamesEn;
443 function getMathNames() {
444 global $wgMathNamesEn;
445 return $wgMathNamesEn;
448 function getDateFormats() {
449 global $wgDateFormatsEn;
450 return $wgDateFormatsEn;
453 function getUserToggles() {
454 global $wgUserTogglesEn;
455 return $wgUserTogglesEn;
458 function getUserToggle( $tog ) {
459 return wfMsg( "tog-$tog" );
462 function getLanguageNames() {
463 global $wgLanguageNamesEn;
464 return $wgLanguageNamesEn;
467 function getLanguageName( $code ) {
468 global $wgLanguageNamesEn;
469 if ( ! array_key_exists( $code, $wgLanguageNamesEn ) ) {
470 return '';
472 return $wgLanguageNamesEn[$code];
475 function getMonthName( $key ) {
476 global $wgMonthNamesEn, $wgContLang;
477 // see who called us and use the correct message function
478 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
479 return wfMsgForContent($wgMonthNamesEn[$key-1]);
480 else
481 return wfMsg($wgMonthNamesEn[$key-1]);
484 /* by default we just return base form */
485 function getMonthNameGen( $key ) {
486 return $this->getMonthName( $key );
489 function getMonthAbbreviation( $key ) {
490 global $wgMonthAbbreviationsEn, $wgContLang;
491 // see who called us and use the correct message function
492 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
493 return wfMsgForContent(@$wgMonthAbbreviationsEn[$key-1]);
494 else
495 return wfMsg(@$wgMonthAbbreviationsEn[$key-1]);
498 function getWeekdayName( $key ) {
499 global $wgWeekdayNamesEn, $wgContLang;
500 // see who called us and use the correct message function
501 if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
502 return wfMsgForContent($wgWeekdayNamesEn[$key-1]);
503 else
504 return wfMsg($wgWeekdayNamesEn[$key-1]);
508 * Used by date() and time() to adjust the time output.
509 * @public
510 * @param int $ts the time in date('YmdHis') format
511 * @param mixed $tz adjust the time by this amount (default false,
512 * mean we get user timecorrection setting)
513 * @return int
516 function userAdjust( $ts, $tz = false ) {
517 global $wgUser, $wgLocalTZoffset;
519 if (!$tz) {
520 $tz = $wgUser->getOption( 'timecorrection' );
523 # minutes and hours differences:
524 $minDiff = 0;
525 $hrDiff = 0;
527 if ( $tz === '' ) {
528 # Global offset in minutes.
529 if( isset($wgLocalTZoffset) ) {
530 $hrDiff = $wgLocalTZoffset % 60;
531 $minDiff = $wgLocalTZoffset - ($hrDiff * 60);
533 } elseif ( strpos( $tz, ':' ) !== false ) {
534 $tzArray = explode( ':', $tz );
535 $hrDiff = intval($tzArray[0]);
536 $minDiff = intval($hrDiff < 0 ? -$tzArray[1] : $tzArray[1]);
537 } else {
538 $hrDiff = intval( $tz );
541 # No difference ? Return time unchanged
542 if ( 0 == $hrDiff && 0 == $minDiff ) { return $ts; }
544 # Generate an adjusted date
545 $t = mktime( (
546 (int)substr( $ts, 8, 2) ) + $hrDiff, # Hours
547 (int)substr( $ts, 10, 2 ) + $minDiff, # Minutes
548 (int)substr( $ts, 12, 2 ), # Seconds
549 (int)substr( $ts, 4, 2 ), # Month
550 (int)substr( $ts, 6, 2 ), # Day
551 (int)substr( $ts, 0, 4 ) ); #Year
552 return date( 'YmdHis', $t );
556 * This is meant to be used by time(), date(), and timeanddate() to get
557 * the date preference they're supposed to use, it should be used in
558 * all children.
560 *<code>
561 * function timeanddate([...], $format = true) {
562 * $datePreference = $this->dateFormat($format);
563 * [...]
564 *</code>
566 * @param mixed $usePrefs: if true, the user's preference is used
567 * if false, the site/language default is used
568 * if int/string, assumed to be a format.
569 * @return string
571 function dateFormat( $usePrefs = true ) {
572 global $wgUser;
574 if( is_bool( $usePrefs ) ) {
575 if( $usePrefs ) {
576 $datePreference = $wgUser->getOption( 'date' );
577 } else {
578 $options = $this->getDefaultUserOptions();
579 $datePreference = (string)$options['date'];
581 } else {
582 $datePreference = (string)$usePrefs;
585 // return int
586 if( $datePreference == '' ) {
587 return MW_DATE_DEFAULT;
590 return $datePreference;
594 * @public
595 * @param mixed $ts the time format which needs to be turned into a
596 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
597 * @param bool $adj whether to adjust the time output according to the
598 * user configured offset ($timecorrection)
599 * @param mixed $format true to use user's date format preference
600 * @param string $timecorrection the time offset as returned by
601 * validateTimeZone() in Special:Preferences
602 * @return string
604 function date( $ts, $adj = false, $format = true, $timecorrection = false ) {
605 global $wgUser, $wgAmericanDates;
607 if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
609 $datePreference = $this->dateFormat( $format );
610 if( $datePreference == MW_DATE_DEFAULT ) {
611 $datePreference = $wgAmericanDates ? MW_DATE_MDY : MW_DATE_DMY;
614 $month = $this->formatMonth( substr( $ts, 4, 2 ), $datePreference );
615 $day = $this->formatDay( substr( $ts, 6, 2 ), $datePreference );
616 $year = $this->formatNum( substr( $ts, 0, 4 ), true );
618 switch( $datePreference ) {
619 case MW_DATE_DMY: return "$day $month $year";
620 case MW_DATE_YMD: return "$year $month $day";
621 case MW_DATE_ISO: return substr($ts, 0, 4). '-' . substr($ts, 4, 2). '-' .substr($ts, 6, 2);
622 default: return "$month $day, $year";
627 * @public
628 * @param mixed $ts the time format which needs to be turned into a
629 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
630 * @param bool $adj whether to adjust the time output according to the
631 * user configured offset ($timecorrection)
632 * @param mixed $format true to use user's date format preference
633 * @param string $timecorrection the time offset as returned by
634 * validateTimeZone() in Special:Preferences
635 * @return string
637 function time( $ts, $adj = false, $format = true, $timecorrection = false ) {
638 global $wgUser;
640 if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
641 $datePreference = $this->dateFormat( $format );
643 $sep = $this->timeSeparator( $format );
645 $hh = substr( $ts, 8, 2 );
646 $mm = substr( $ts, 10, 2 );
647 $ss = substr( $ts, 12, 2 );
649 if ( $datePreference != MW_DATE_ISO ) {
650 $hh = $this->formatNum( $hh, true );
651 $mm = $this->formatNum( $mm, true );
652 //$ss = $this->formatNum( $ss, true );
653 return $hh . $sep . $mm;
654 } else {
655 return $hh . ':' . $mm . ':' . $ss;
660 * Default separator character between hours, minutes, and seconds.
661 * Will be used by Language::time() for non-ISO formats.
662 * (ISO will always use a colon.)
663 * @return string
665 function timeSeparator( $format ) {
666 return ':';
670 * String to insert between the time and the date in a combined
671 * string. Should include any relevant whitespace.
672 * @return string
674 function timeDateSeparator( $format ) {
675 return ', ';
679 * Return true if the time should display before the date.
680 * @return bool
681 * @private
683 function timeBeforeDate() {
684 return true;
687 function formatMonth( $month, $format ) {
688 return $this->getMonthName( $month );
691 function formatDay( $day, $format ) {
692 return $this->formatNum( 0 + $day, true );
696 * @public
697 * @param mixed $ts the time format which needs to be turned into a
698 * date('YmdHis') format with wfTimestamp(TS_MW,$ts)
699 * @param bool $adj whether to adjust the time output according to the
700 * user configured offset ($timecorrection)
702 * @param mixed $format what format to return, if it's false output the
703 * default one (default true)
704 * @param string $timecorrection the time offset as returned by
705 * validateTimeZone() in Special:Preferences
706 * @return string
708 function timeanddate( $ts, $adj = false, $format = true, $timecorrection = false) {
709 global $wgUser;
711 $datePreference = $this->dateFormat($format);
712 switch ( $datePreference ) {
713 case MW_DATE_ISO: return $this->date( $ts, $adj, $format, $timecorrection ) . ' ' .
714 $this->time( $ts, $adj, $format, $timecorrection );
715 default:
716 $time = $this->time( $ts, $adj, $format, $timecorrection );
717 $sep = $this->timeDateSeparator( $datePreference );
718 $date = $this->date( $ts, $adj, $format, $timecorrection );
719 return $this->timeBeforeDate( $datePreference )
720 ? $time . $sep . $date
721 : $date . $sep . $time;
725 function getMessage( $key ) {
726 global $wgAllMessagesEn;
727 return @$wgAllMessagesEn[$key];
730 function getAllMessages() {
731 global $wgAllMessagesEn;
732 return $wgAllMessagesEn;
735 function iconv( $in, $out, $string ) {
736 # For most languages, this is a wrapper for iconv
737 return iconv( $in, $out, $string );
740 function ucfirst( $string ) {
741 # For most languages, this is a wrapper for ucfirst()
742 return ucfirst( $string );
745 function uc( $str ) {
746 return strtoupper( $str );
749 function lcfirst( $s ) {
750 return strtolower( $s{0} ). substr( $s, 1 );
753 function lc( $str ) {
754 return strtolower( $str );
757 function checkTitleEncoding( $s ) {
758 global $wgInputEncoding;
760 # Check for UTF-8 URLs; Internet Explorer produces these if you
761 # type non-ASCII chars in the URL bar or follow unescaped links.
762 $ishigh = preg_match( '/[\x80-\xff]/', $s);
763 $isutf = ($ishigh ? preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
764 '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s ) : true );
766 if( ($wgInputEncoding != 'utf-8') and $ishigh and $isutf )
767 return @iconv( 'UTF-8', $wgInputEncoding, $s );
769 if( ($wgInputEncoding == 'utf-8') and $ishigh and !$isutf )
770 return utf8_encode( $s );
772 # Other languages can safely leave this function, or replace
773 # it with one to detect and convert another legacy encoding.
774 return $s;
778 * Some languages have special punctuation to strip out
779 * or characters which need to be converted for MySQL's
780 * indexing to grok it correctly. Make such changes here.
782 * @param string $in
783 * @return string
785 function stripForSearch( $in ) {
786 return strtolower( $in );
789 function convertForSearchResult( $termsArray ) {
790 # some languages, e.g. Chinese, need to do a conversion
791 # in order for search results to be displayed correctly
792 return $termsArray;
796 * Get the first character of a string. In ASCII, return
797 * first byte of the string. UTF8 and others have to
798 * overload this.
800 * @param string $s
801 * @return string
803 function firstChar( $s ) {
804 return $s[0];
807 function initEncoding() {
808 # Some languages may have an alternate char encoding option
809 # (Esperanto X-coding, Japanese furigana conversion, etc)
810 # If this language is used as the primary content language,
811 # an override to the defaults can be set here on startup.
812 #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
815 function setAltEncoding() {
816 # Some languages may have an alternate char encoding option
817 # (Esperanto X-coding, Japanese furigana conversion, etc)
818 # If 'altencoding' is checked in user prefs, this gives a
819 # chance to swap out the default encoding settings.
820 #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
823 function recodeForEdit( $s ) {
824 # For some languages we'll want to explicitly specify
825 # which characters make it into the edit box raw
826 # or are converted in some way or another.
827 # Note that if wgOutputEncoding is different from
828 # wgInputEncoding, this text will be further converted
829 # to wgOutputEncoding.
830 global $wgInputEncoding, $wgEditEncoding;
831 if( $wgEditEncoding == '' or
832 $wgEditEncoding == $wgInputEncoding ) {
833 return $s;
834 } else {
835 return $this->iconv( $wgInputEncoding, $wgEditEncoding, $s );
839 function recodeInput( $s ) {
840 # Take the previous into account.
841 global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
842 if($wgEditEncoding != "") {
843 $enc = $wgEditEncoding;
844 } else {
845 $enc = $wgOutputEncoding;
847 if( $enc == $wgInputEncoding ) {
848 return $s;
849 } else {
850 return $this->iconv( $enc, $wgInputEncoding, $s );
855 * For right-to-left language support
857 * @return bool
859 function isRTL() { return false; }
862 * A hidden direction mark (LRM or RLM), depending on the language direction
864 * @return string
866 function getDirMark() { return $this->isRTL() ? "\xE2\x80\x8F" : "\xE2\x80\x8E"; }
869 * To allow "foo[[bar]]" to extend the link over the whole word "foobar"
871 * @return bool
873 function linkPrefixExtension() { return false; }
875 function &getMagicWords() {
876 global $wgMagicWordsEn;
877 return $wgMagicWordsEn;
880 # Fill a MagicWord object with data from here
881 function getMagic( &$mw ) {
882 if ( !isset( $this->mMagicExtensions ) ) {
883 $this->mMagicExtensions = array();
884 wfRunHooks( 'LanguageGetMagic', array( &$this->mMagicExtensions, $this->getCode() ) );
886 if ( isset( $this->mMagicExtensions[$mw->mId] ) ) {
887 $rawEntry = $this->mMagicExtensions[$mw->mId];
888 } else {
889 $magicWords =& $this->getMagicWords();
890 if ( isset( $magicWords[$mw->mId] ) ) {
891 $rawEntry = $magicWords[$mw->mId];
892 } else {
893 # Fall back to English if local list is incomplete
894 $magicWords =& Language::getMagicWords();
895 $rawEntry = $magicWords[$mw->mId];
899 $mw->mCaseSensitive = $rawEntry[0];
900 $mw->mSynonyms = array_slice( $rawEntry, 1 );
904 * Italic is unsuitable for some languages
906 * @public
908 * @param string $text The text to be emphasized.
909 * @return string
911 function emphasize( $text ) {
912 return "<em>$text</em>";
916 * Normally we output all numbers in plain en_US style, that is
917 * 293,291.235 for twohundredninetythreethousand-twohundredninetyone
918 * point twohundredthirtyfive. However this is not sutable for all
919 * languages, some such as Pakaran want ੨੯੩,੨੯੫.੨੩੫ and others such as
920 * Icelandic just want to use commas instead of dots, and dots instead
921 * of commas like "293.291,235".
923 * An example of this function being called:
924 * <code>
925 * wfMsg( 'message', $wgLang->formatNum( $num ) )
926 * </code>
928 * See LanguageGu.php for the Gujarati implementation and
929 * LanguageIs.php for the , => . and . => , implementation.
931 * @todo check if it's viable to use localeconv() for the decimal
932 * seperator thing.
933 * @public
934 * @param mixed $number the string to be formatted, should be an integer or
935 * a floating point number.
936 * @param bool $nocommafy Set to true for special numbers like dates
937 * @return string
939 function formatNum( $number, $nocommafy = false ) {
940 global $wgTranslateNumerals;
941 if (!$nocommafy) {
942 $number = $this->commafy($number);
943 $s = $this->separatorTransformTable();
944 if (!is_null($s)) { $number = strtr($number, $s); }
947 if ($wgTranslateNumerals) {
948 $s = $this->digitTransformTable();
949 if (!is_null($s)) { $number = strtr($number, $s); }
952 return $number;
956 * Adds commas to a given number
958 * @param mixed $_
959 * @return string
961 function commafy($_) {
962 return strrev((string)preg_replace('/(\d{3})(?=\d)(?!\d*\.)/','$1,',strrev($_)));
965 function digitTransformTable() {
966 return null;
969 function separatorTransformTable() {
970 return null;
975 * For the credit list in includes/Credits.php (action=credits)
977 * @param array $l
978 * @return string
980 function listToText( $l ) {
981 $s = '';
982 $m = count($l) - 1;
983 for ($i = $m; $i >= 0; $i--) {
984 if ($i == $m) {
985 $s = $l[$i];
986 } else if ($i == $m - 1) {
987 $s = $l[$i] . ' ' . wfMsg('and') . ' ' . $s;
988 } else {
989 $s = $l[$i] . ', ' . $s;
992 return $s;
995 # Crop a string from the beginning or end to a certain number of bytes.
996 # (Bytes are used because our storage has limited byte lengths for some
997 # columns in the database.) Multibyte charsets will need to make sure that
998 # only whole characters are included!
1000 # $length does not include the optional ellipsis.
1001 # If $length is negative, snip from the beginning
1002 function truncate( $string, $length, $ellipsis = '' ) {
1003 if( $length == 0 ) {
1004 return $ellipsis;
1006 if ( strlen( $string ) <= abs( $length ) ) {
1007 return $string;
1009 if( $length > 0 ) {
1010 $string = substr( $string, 0, $length );
1011 return $string . $ellipsis;
1012 } else {
1013 $string = substr( $string, $length );
1014 return $ellipsis . $string;
1019 * Grammatical transformations, needed for inflected languages
1020 * Invoked by putting {{grammar:case|word}} in a message
1022 * @param string $word
1023 * @param string $case
1024 * @return string
1026 function convertGrammar( $word, $case ) {
1027 global $wgGrammarForms;
1028 if ( isset($wgGrammarForms['en'][$case][$word]) ) {
1029 return $wgGrammarForms['en'][$case][$word];
1031 return $word;
1035 * Plural form transformations, needed for some languages.
1036 * For example, where are 3 form of plural in Russian and Polish,
1037 * depending on "count mod 10". See [[w:Plural]]
1038 * For English it is pretty simple.
1040 * Invoked by putting {{plural:count|wordform1|wordform2}}
1041 * or {{plural:count|wordform1|wordform2|wordform3}}
1043 * Example: {{plural:{{NUMBEROFARTICLES}}|article|articles}}
1045 * @param integer $count
1046 * @param string $wordform1
1047 * @param string $wordform2
1048 * @param string $wordform3 (optional)
1049 * @return string
1051 function convertPlural( $count, $wordform1, $wordform2, $wordform3) {
1052 return $count == '1' ? $wordform1 : $wordform2;
1056 * For translaing of expiry times
1057 * @param string The validated block time in English
1058 * @return Somehow translated block time
1059 * @see LanguageFi.php for example implementation
1061 function translateBlockExpiry( $str ) {
1063 $scBlockExpiryOptions = wfMsg( 'ipboptions' );
1065 if ( $scBlockExpiryOptions == '-') {
1066 return $str;
1069 foreach (explode(',', $scBlockExpiryOptions) as $option) {
1070 if ( strpos($option, ":") === false )
1071 continue;
1072 list($show, $value) = explode(":", $option);
1073 if ( strcmp ( $str, $value) == 0 )
1074 return '<span title="' . htmlspecialchars($str). '">' .
1075 htmlspecialchars( trim( $show ) ) . '</span>';
1078 return $str;
1082 * languages like Chinese need to be segmented in order for the diff
1083 * to be of any use
1085 * @param string $text
1086 * @return string
1088 function segmentForDiff( $text ) {
1089 return $text;
1093 * and unsegment to show the result
1095 * @param string $text
1096 * @return string
1098 function unsegmentForDiff( $text ) {
1099 return $text;
1102 # convert text to different variants of a language.
1103 function convert( $text, $isTitle = false) {
1104 return $this->mConverter->convert($text, $isTitle);
1107 # Convert text from within Parser
1108 function parserConvert( $text, &$parser ) {
1109 return $this->mConverter->parserConvert( $text, $parser );
1113 * Perform output conversion on a string, and encode for safe HTML output.
1114 * @param string $text
1115 * @param bool $isTitle -- wtf?
1116 * @return string
1117 * @todo this should get integrated somewhere sane
1119 function convertHtml( $text, $isTitle = false ) {
1120 return htmlspecialchars( $this->convert( $text, $isTitle ) );
1123 function convertCategoryKey( $key ) {
1124 return $this->mConverter->convertCategoryKey( $key );
1128 * get the list of variants supported by this langauge
1129 * see sample implementation in LanguageZh.php
1131 * @return array an array of language codes
1133 function getVariants() {
1134 return $this->mConverter->getVariants();
1138 function getPreferredVariant() {
1139 return $this->mConverter->getPreferredVariant();
1143 * if a language supports multiple variants, it is
1144 * possible that non-existing link in one variant
1145 * actually exists in another variant. this function
1146 * tries to find it. See e.g. LanguageZh.php
1148 * @param string $link the name of the link
1149 * @param mixed $nt the title object of the link
1150 * @return null the input parameters may be modified upon return
1152 function findVariantLink( &$link, &$nt ) {
1153 $this->mConverter->findVariantLink($link, $nt);
1157 * returns language specific options used by User::getPageRenderHash()
1158 * for example, the preferred language variant
1160 * @return string
1161 * @public
1163 function getExtraHashOptions() {
1164 return $this->mConverter->getExtraHashOptions();
1168 * for languages that support multiple variants, the title of an
1169 * article may be displayed differently in different variants. this
1170 * function returns the apporiate title defined in the body of the article.
1172 * @return string
1174 function getParsedTitle() {
1175 return $this->mConverter->getParsedTitle();
1179 * Enclose a string with the "no conversion" tag. This is used by
1180 * various functions in the Parser
1182 * @param string $text text to be tagged for no conversion
1183 * @return string the tagged text
1185 function markNoConversion( $text ) {
1186 return $this->mConverter->markNoConversion( $text );
1190 * A regular expression to match legal word-trailing characters
1191 * which should be merged onto a link of the form [[foo]]bar.
1193 * @return string
1194 * @public
1196 function linkTrail() {
1197 return $this->getMessage( 'linktrail' );
1200 function getLangObj() {
1201 return $this;
1205 * Get the RFC 3066 code for this language object
1207 function getCode() {
1208 return str_replace( '_', '-', strtolower( substr( get_class( $this ), 8 ) ) );
1214 # FIXME: Merge all UTF-8 support code into Language base class.
1215 # We no longer support Latin-1 charset.
1216 require_once( 'LanguageUtf8.php' );
1218 # This should fail gracefully if there's not a localization available
1219 wfSuppressWarnings();
1220 // Preload base classes to work around APC/PHP5 bug
1221 include_once( 'Language' . str_replace( '-', '_', ucfirst( $wgLanguageCode ) ) . '.deps.php' );
1222 include_once( 'Language' . str_replace( '-', '_', ucfirst( $wgLanguageCode ) ) . '.php' );
1223 wfRestoreWarnings();