* (bug 7609) Add some more '*-summary' messages to MessagesEn.php with empty
[lhc/web/wiklou.git] / maintenance / language / languages.inc
1 <?php
2 /**
3 * Handle messages in the language files.
4 *
5 * @package MediaWiki
6 * @subpackage Maintenance
7 */
8
9 class languages {
10 private $mLanguages; # List of languages
11 private $mRawMessages; # Raw list of the messages in each language
12 private $mMessages; # Messages in each language (except for English), divided to groups
13 private $mGeneralMessages; # General messages in English, divided to groups
14 private $mIgnoredMessages = array(
15 'sidebar',
16 'addsection',
17 'anonnotice',
18 'catseparator',
19 'googlesearch',
20 'exif-make-value',
21 'exif-model-value',
22 'exif-software-value',
23 'history_copyright',
24 'licenses',
25 'loginend',
26 'loginlanguagelinks',
27 'markaspatrolledlink',
28 'newarticletextanon',
29 'noarticletextanon',
30 'number_of_watching_users_RCview',
31 'pubmedurl',
32 'randompage-url',
33 'recentchanges-url',
34 'rfcurl',
35 'shareddescriptionfollows',
36 'signupend',
37 'sitenotice',
38 'sitesubtitle',
39 'sitetitle',
40 'talkpagetext',
41 'trackback',
42 'trackbackexcerpt',
43 'widthheight',
44 ); # All the messages which should be exist only in the English file
45 private $mOptionalMessages = array(
46 'imgmultigotopost',
47 'linkprefix',
48 'allpages-summary',
49 'booksources-summary',
50 'ipblocklist-summary',
51 'listusers-summary',
52 'longpages-summary',
53 'preferences-summary',
54 'specialpages-summary',
55 'whatlinkshere-summary',
56 'whatlinkshere-barrow',
57 'imagelist-summary',
58 'mimesearch-summary',
59 'listredirects-summary',
60 'uncategorizedpages-summary',
61 'uncategorizedcategories-summary',
62 'uncategorizedimages-summary',
63 'popularpages-summary',
64 'wantedcategories-summary',
65 'wantedpages-summary',
66 'mostlinked-summary',
67 'mostlinkedcategories-summary',
68 'mostcategories-summary',
69 'mostimages-summary',
70 'mostrevisions-summary',
71 'prefixindex-summary',
72 'shortpages-summary',
73 'newpages-summary',
74 'ancientpages-summary',
75 'newimages-summary',
76 'unwatchedpages-summary',
77 'userrights-summary',
78 'brokenredirects-summary',
79 'deadendpages-summary',
80 'disambiguations-summary',
81 'doubleredirects-summary',
82 'lonelypages-summary',
83 'unusedtemplates-summary',
84 'variantname-zh-cn',
85 'variantname-zh-tw',
86 'variantname-zh-hk',
87 'variantname-zh-sg',
88 'variantname-zh',
89 'variantname-sr-ec',
90 'variantname-sr-el',
91 'variantname-sr-jc',
92 'variantname-sr-jl',
93 'variantname-sr',
94 'variantname-kk-tr',
95 'variantname-kk-kz',
96 'variantname-kk-cn',
97 'variantname-kk',
98 ); # All the messages which may be translated or not, depending on the language
99 private $mEXIFMessages = array(
100 'exif-imagewidth',
101 'exif-imagelength',
102 'exif-bitspersample',
103 'exif-compression',
104 'exif-photometricinterpretation',
105 'exif-orientation',
106 'exif-samplesperpixel',
107 'exif-planarconfiguration',
108 'exif-ycbcrsubsampling',
109 'exif-ycbcrpositioning',
110 'exif-xresolution',
111 'exif-yresolution',
112 'exif-resolutionunit',
113 'exif-stripoffsets',
114 'exif-rowsperstrip',
115 'exif-stripbytecounts',
116 'exif-jpeginterchangeformat',
117 'exif-jpeginterchangeformatlength',
118 'exif-transferfunction',
119 'exif-whitepoint',
120 'exif-primarychromaticities',
121 'exif-ycbcrcoefficients',
122 'exif-referenceblackwhite',
123 'exif-datetime',
124 'exif-imagedescription',
125 'exif-make',
126 'exif-model',
127 'exif-software',
128 'exif-artist',
129 'exif-copyright',
130 'exif-exifversion',
131 'exif-flashpixversion',
132 'exif-colorspace',
133 'exif-componentsconfiguration',
134 'exif-compressedbitsperpixel',
135 'exif-pixelydimension',
136 'exif-pixelxdimension',
137 'exif-makernote',
138 'exif-usercomment',
139 'exif-relatedsoundfile',
140 'exif-datetimeoriginal',
141 'exif-datetimedigitized',
142 'exif-subsectime',
143 'exif-subsectimeoriginal',
144 'exif-subsectimedigitized',
145 'exif-exposuretime',
146 'exif-exposuretime-format',
147 'exif-fnumber',
148 'exif-fnumber-format',
149 'exif-exposureprogram',
150 'exif-spectralsensitivity',
151 'exif-isospeedratings',
152 'exif-oecf',
153 'exif-shutterspeedvalue',
154 'exif-aperturevalue',
155 'exif-brightnessvalue',
156 'exif-exposurebiasvalue',
157 'exif-maxaperturevalue',
158 'exif-subjectdistance',
159 'exif-meteringmode',
160 'exif-lightsource',
161 'exif-flash',
162 'exif-focallength',
163 'exif-focallength-format',
164 'exif-subjectarea',
165 'exif-flashenergy',
166 'exif-spatialfrequencyresponse',
167 'exif-focalplanexresolution',
168 'exif-focalplaneyresolution',
169 'exif-focalplaneresolutionunit',
170 'exif-subjectlocation',
171 'exif-exposureindex',
172 'exif-sensingmethod',
173 'exif-filesource',
174 'exif-scenetype',
175 'exif-cfapattern',
176 'exif-customrendered',
177 'exif-exposuremode',
178 'exif-whitebalance',
179 'exif-digitalzoomratio',
180 'exif-focallengthin35mmfilm',
181 'exif-scenecapturetype',
182 'exif-gaincontrol',
183 'exif-contrast',
184 'exif-saturation',
185 'exif-sharpness',
186 'exif-devicesettingdescription',
187 'exif-subjectdistancerange',
188 'exif-imageuniqueid',
189 'exif-gpsversionid',
190 'exif-gpslatituderef',
191 'exif-gpslatitude',
192 'exif-gpslongituderef',
193 'exif-gpslongitude',
194 'exif-gpsaltituderef',
195 'exif-gpsaltitude',
196 'exif-gpstimestamp',
197 'exif-gpssatellites',
198 'exif-gpsstatus',
199 'exif-gpsmeasuremode',
200 'exif-gpsdop',
201 'exif-gpsspeedref',
202 'exif-gpsspeed',
203 'exif-gpstrackref',
204 'exif-gpstrack',
205 'exif-gpsimgdirectionref',
206 'exif-gpsimgdirection',
207 'exif-gpsmapdatum',
208 'exif-gpsdestlatituderef',
209 'exif-gpsdestlatitude',
210 'exif-gpsdestlongituderef',
211 'exif-gpsdestlongitude',
212 'exif-gpsdestbearingref',
213 'exif-gpsdestbearing',
214 'exif-gpsdestdistanceref',
215 'exif-gpsdestdistance',
216 'exif-gpsprocessingmethod',
217 'exif-gpsareainformation',
218 'exif-gpsdatestamp',
219 'exif-gpsdifferential',
220 'exif-compression-1',
221 'exif-compression-6',
222 'exif-photometricinterpretation-2',
223 'exif-photometricinterpretation-6',
224 'exif-orientation-1',
225 'exif-orientation-2',
226 'exif-orientation-3',
227 'exif-orientation-4',
228 'exif-orientation-5',
229 'exif-orientation-6',
230 'exif-orientation-7',
231 'exif-orientation-8',
232 'exif-planarconfiguration-1',
233 'exif-planarconfiguration-2',
234 'exif-xyresolution-i',
235 'exif-xyresolution-c',
236 'exif-colorspace-1',
237 'exif-colorspace-ffff.h',
238 'exif-componentsconfiguration-0',
239 'exif-componentsconfiguration-1',
240 'exif-componentsconfiguration-2',
241 'exif-componentsconfiguration-3',
242 'exif-componentsconfiguration-4',
243 'exif-componentsconfiguration-5',
244 'exif-componentsconfiguration-6',
245 'exif-exposureprogram-0',
246 'exif-exposureprogram-1',
247 'exif-exposureprogram-2',
248 'exif-exposureprogram-3',
249 'exif-exposureprogram-4',
250 'exif-exposureprogram-5',
251 'exif-exposureprogram-6',
252 'exif-exposureprogram-7',
253 'exif-exposureprogram-8',
254 'exif-subjectdistance-value',
255 'exif-meteringmode-0',
256 'exif-meteringmode-1',
257 'exif-meteringmode-2',
258 'exif-meteringmode-3',
259 'exif-meteringmode-4',
260 'exif-meteringmode-5',
261 'exif-meteringmode-6',
262 'exif-meteringmode-255',
263 'exif-lightsource-0',
264 'exif-lightsource-1',
265 'exif-lightsource-2',
266 'exif-lightsource-3',
267 'exif-lightsource-4',
268 'exif-lightsource-9',
269 'exif-lightsource-10',
270 'exif-lightsource-11',
271 'exif-lightsource-12',
272 'exif-lightsource-13',
273 'exif-lightsource-14',
274 'exif-lightsource-15',
275 'exif-lightsource-17',
276 'exif-lightsource-18',
277 'exif-lightsource-19',
278 'exif-lightsource-20',
279 'exif-lightsource-21',
280 'exif-lightsource-22',
281 'exif-lightsource-23',
282 'exif-lightsource-24',
283 'exif-lightsource-255',
284 'exif-focalplaneresolutionunit-2',
285 'exif-sensingmethod-1',
286 'exif-sensingmethod-2',
287 'exif-sensingmethod-3',
288 'exif-sensingmethod-4',
289 'exif-sensingmethod-5',
290 'exif-sensingmethod-7',
291 'exif-sensingmethod-8',
292 'exif-filesource-3',
293 'exif-scenetype-1',
294 'exif-customrendered-0',
295 'exif-customrendered-1',
296 'exif-exposuremode-0',
297 'exif-exposuremode-1',
298 'exif-exposuremode-2',
299 'exif-whitebalance-0',
300 'exif-whitebalance-1',
301 'exif-scenecapturetype-0',
302 'exif-scenecapturetype-1',
303 'exif-scenecapturetype-2',
304 'exif-scenecapturetype-3',
305 'exif-gaincontrol-0',
306 'exif-gaincontrol-1',
307 'exif-gaincontrol-2',
308 'exif-gaincontrol-3',
309 'exif-gaincontrol-4',
310 'exif-contrast-0',
311 'exif-contrast-1',
312 'exif-contrast-2',
313 'exif-saturation-0',
314 'exif-saturation-1',
315 'exif-saturation-2',
316 'exif-sharpness-0',
317 'exif-sharpness-1',
318 'exif-sharpness-2',
319 'exif-subjectdistancerange-0',
320 'exif-subjectdistancerange-1',
321 'exif-subjectdistancerange-2',
322 'exif-subjectdistancerange-3',
323 'exif-gpslatitude-n',
324 'exif-gpslatitude-s',
325 'exif-gpslongitude-e',
326 'exif-gpslongitude-w',
327 'exif-gpsstatus-a',
328 'exif-gpsstatus-v',
329 'exif-gpsmeasuremode-2',
330 'exif-gpsmeasuremode-3',
331 'exif-gpsspeed-k',
332 'exif-gpsspeed-m',
333 'exif-gpsspeed-n',
334 'exif-gpsdirection-t',
335 'exif-gpsdirection-m',
336 ); # All the EXIF messages, may be set as optional if defined as such
337
338 /**
339 * Load the list of languages: all the Messages*.php
340 * files in the languages directory.
341 *
342 * @param $exif Treat the EXIF messages?
343 */
344 function __construct( $exif = true ) {
345 $this->mLanguages = array_keys( Language::getLanguageNames( true ) );
346 sort( $this->mLanguages );
347 if ( !$exif ) {
348 $this->mOptionalMessages = array_merge( $this->mOptionalMessages, $this->mEXIFMessages );
349 }
350 }
351
352 /**
353 * Get the language list.
354 *
355 * @return The language list.
356 */
357 public function getLanguages() {
358 return $this->mLanguages;
359 }
360
361 /**
362 * Load the raw messages for a specific langauge from the messages file.
363 *
364 * @param $code The langauge code.
365 */
366 private function loadRawMessages( $code ) {
367 if ( isset( $this->mRawMessages[$code] ) ) {
368 return;
369 }
370 $filename = Language::getMessagesFileName( $code );
371 if ( file_exists( $filename ) ) {
372 require( $filename );
373 if ( isset( $messages ) ) {
374 $this->mRawMessages[$code] = $messages;
375 } else {
376 $this->mRawMessages[$code] = array();
377 }
378 } else {
379 $this->mRawMessages[$code] = array();
380 }
381 }
382
383 /**
384 * Load the messages for a specific language (which is not English) and divide them to groups:
385 * all - all the messages.
386 * required - messages which should be translated in order to get a complete translation.
387 * optional - messages which can be translated, the fallback translation is used if not translated.
388 * obsolete - messages which should not be translated, either because they are not exist, or they are ignored messages.
389 * translated - messages which are either required or optional, but translated from English and needed.
390 *
391 * @param $code The language code.
392 */
393 private function loadMessages( $code ) {
394 if ( isset( $this->mMessages[$code] ) ) {
395 return;
396 }
397 $this->loadRawMessages( $code );
398 $this->loadGeneralMessages();
399 $this->mMessages[$code]['all'] = $this->mRawMessages[$code];
400 $this->mMessages[$code]['required'] = array();
401 $this->mMessages[$code]['optional'] = array();
402 $this->mMessages[$code]['obsolete'] = array();
403 $this->mMessages[$code]['translated'] = array();
404 foreach ( $this->mMessages[$code]['all'] as $key => $value ) {
405 if ( isset( $this->mGeneralMessages['required'][$key] ) ) {
406 $this->mMessages[$code]['required'][$key] = $value;
407 $this->mMessages[$code]['translated'][$key] = $value;
408 } else if ( isset( $this->mGeneralMessages['optional'][$key] ) ) {
409 $this->mMessages[$code]['optional'][$key] = $value;
410 $this->mMessages[$code]['translated'][$key] = $value;
411 } else {
412 $this->mMessages[$code]['obsolete'][$key] = $value;
413 }
414 }
415 }
416
417 /**
418 * Load the messages for English and divide them to groups:
419 * all - all the messages.
420 * required - messages which should be translated to other languages in order to get a complete translation.
421 * optional - messages which can be translated to other languages, but it's not required for a complete translation.
422 * ignored - messages which should not be translated to other languages.
423 * translatable - messages which are either required or optional, but can be translated from English.
424 */
425 private function loadGeneralMessages() {
426 if ( isset( $this->mGeneralMessages ) ) {
427 return;
428 }
429 $this->loadRawMessages( 'en' );
430 $this->mGeneralMessages['all'] = $this->mRawMessages['en'];
431 $this->mGeneralMessages['required'] = array();
432 $this->mGeneralMessages['optional'] = array();
433 $this->mGeneralMessages['ignored'] = array();
434 $this->mGeneralMessages['translatable'] = array();
435 foreach ( $this->mGeneralMessages['all'] as $key => $value ) {
436 if ( in_array( $key, $this->mIgnoredMessages ) ) {
437 $this->mGeneralMessages['ignored'][$key] = $value;
438 } else if ( in_array( $key, $this->mOptionalMessages ) ) {
439 $this->mGeneralMessages['optional'][$key] = $value;
440 $this->mGeneralMessages['translatable'][$key] = $value;
441 } else {
442 $this->mGeneralMessages['required'][$key] = $value;
443 $this->mGeneralMessages['translatable'][$key] = $value;
444 }
445 }
446 }
447
448 /**
449 * Get all the messages for a specific langauge (not English), without the
450 * fallback language messages, divided to groups:
451 * all - all the messages.
452 * required - messages which should be translated in order to get a complete translation.
453 * optional - messages which can be translated, the fallback translation is used if not translated.
454 * obsolete - messages which should not be translated, either because they are not exist, or they are ignored messages.
455 * translated - messages which are either required or optional, but translated from English and needed.
456 *
457 * @param $code The langauge code.
458 *
459 * @return The messages in this language.
460 */
461 public function getMessages( $code ) {
462 $this->loadMessages( $code );
463 return $this->mMessages[$code];
464 }
465
466 /**
467 * Get all the general English messages, divided to groups:
468 * all - all the messages.
469 * required - messages which should be translated to other languages in order to get a complete translation.
470 * optional - messages which can be translated to other languages, but it's not required for a complete translation.
471 * ignored - messages which should not be translated to other languages.
472 * translatable - messages which are either required or optional, but can be translated from English.
473 *
474 * @return The general English messages.
475 */
476 public function getGeneralMessages() {
477 $this->loadGeneralMessages();
478 return $this->mGeneralMessages;
479 }
480
481 /**
482 * Get the untranslated messages for a specific language.
483 *
484 * @param $code The langauge code.
485 *
486 * @return The untranslated messages for this language.
487 */
488 public function getUntranslatedMessages( $code ) {
489 $this->loadGeneralMessages();
490 $this->loadMessages( $code );
491 $requiredGeneralMessages = array_keys( $this->mGeneralMessages['required'] );
492 $requiredMessages = array_keys( $this->mMessages[$code]['required'] );
493 $untranslatedMessages = array();
494 foreach ( array_diff( $requiredGeneralMessages, $requiredMessages ) as $key ) {
495 $untranslatedMessages[$key] = $this->mGeneralMessages['required'][$key];
496 }
497 return $untranslatedMessages;
498 }
499
500 /**
501 * Get the duplicate messages for a specific language.
502 *
503 * @param $code The langauge code.
504 *
505 * @return The duplicate messages for this language.
506 */
507 public function getDuplicateMessages( $code ) {
508 $this->loadGeneralMessages();
509 $this->loadMessages( $code );
510 $duplicateMessages = array();
511 foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
512 if ( $this->mGeneralMessages['translatable'][$key] == $value ) {
513 $duplicateMessages[$key] = $value;
514 }
515 }
516 return $duplicateMessages;
517 }
518
519 /**
520 * Get the messages which do not use some variables.
521 *
522 * @param $code The langauge code.
523 *
524 * @return The messages which do not use some variables in this language.
525 */
526 public function getMessagesWithoutVariables( $code ) {
527 $this->loadGeneralMessages();
528 $this->loadMessages( $code );
529 $variables = array( '\$1', '\$2', '\$3', '\$4', '\$5', '\$6', '\$7', '\$8', '\$9' );
530 $messagesWithoutVariables = array();
531 foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
532 $missing = false;
533 foreach ( $variables as $var ) {
534 if ( preg_match( "/$var/sU", $this->mGeneralMessages['translatable'][$key] ) &&
535 !preg_match( "/$var/sU", $value ) ) {
536 $missing = true;
537 }
538 }
539 if ( $missing ) {
540 $messagesWithoutVariables[$key] = $value;
541 }
542 }
543 return $messagesWithoutVariables;
544 }
545
546 /**
547 * Get the empty messages.
548 *
549 * @param $code The langauge code.
550 *
551 * @return The empty messages for this language.
552 */
553 public function getEmptyMessages( $code ) {
554 $this->loadGeneralMessages();
555 $this->loadMessages( $code );
556 $emptyMessages = array();
557 foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
558 if ( $value === '' || $value === '-' ) {
559 $emptyMessages[$key] = $value;
560 }
561 }
562 return $emptyMessages;
563 }
564
565 /**
566 * Get the messages with trailing whitespace.
567 *
568 * @param $code The langauge code.
569 *
570 * @return The messages with trailing whitespace in this language.
571 */
572 public function getMessagesWithWhitespace( $code ) {
573 $this->loadGeneralMessages();
574 $this->loadMessages( $code );
575 $messagesWithWhitespace = array();
576 foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
577 if ( $this->mGeneralMessages['translatable'][$key] !== '' && $value !== rtrim( $value ) ) {
578 $messagesWithWhitespace[$key] = $value;
579 }
580 }
581 return $messagesWithWhitespace;
582 }
583
584 /**
585 * Get the non-XHTML messages.
586 *
587 * @param $code The langauge code.
588 *
589 * @return The non-XHTML messages for this language.
590 */
591 public function getNonXHTMLMessages( $code ) {
592 $this->loadGeneralMessages();
593 $this->loadMessages( $code );
594 $wrongPhrases = array(
595 '<hr *\\?>',
596 '<br *\\?>',
597 '<hr/>',
598 '<br/>',
599 );
600 $wrongPhrases = '~(' . implode( '|', $wrongPhrases ) . ')~sDu';
601 $nonXHTMLMessages = array();
602 foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
603 if ( preg_match( $wrongPhrases, $value ) ) {
604 $nonXHTMLMessages[$key] = $value;
605 }
606 }
607 return $nonXHTMLMessages;
608 }
609
610 /**
611 * Get the messages which include wrong characters.
612 *
613 * @param $code The langauge code.
614 *
615 * @return The messages which include wrong characters in this language.
616 */
617 public function getMessagesWithWrongChars( $code ) {
618 $this->loadGeneralMessages();
619 $this->loadMessages( $code );
620 $wrongChars = array(
621 '[LRM]' => "\xE2\x80\x8E",
622 '[RLM]' => "\xE2\x80\x8F",
623 '[LRE]' => "\xE2\x80\xAA",
624 '[RLE]' => "\xE2\x80\xAB",
625 '[POP]' => "\xE2\x80\xAC",
626 '[LRO]' => "\xE2\x80\xAD",
627 '[RLO]' => "\xE2\x80\xAB",
628 '[ZWSP]'=> "\xE2\x80\x8B",
629 '[NBSP]'=> "\xC2\xA0",
630 '[WJ]' => "\xE2\x81\xA0",
631 '[BOM]' => "\xEF\xBB\xBF",
632 '[FFFD]'=> "\xEF\xBF\xBD",
633 );
634 $wrongRegExp = '/(' . implode( '|', array_values( $wrongChars ) ) . ')/sDu';
635 $wrongCharsMessages = array();
636 foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
637 if ( preg_match( $wrongRegExp, $value ) ) {
638 foreach ( $wrongChars as $viewableChar => $hiddenChar ) {
639 $value = str_replace( $hiddenChar, $viewableChar, $value );
640 }
641 $wrongCharsMessages[$key] = $value;
642 }
643 }
644 return $wrongCharsMessages;
645 }
646
647 /**
648 * Output a messages list
649 *
650 * @param $messages The messages list
651 * @param $code The language code
652 * @param $text The text to show before the list (optional)
653 * @param $level The display level (optional)
654 * @param $links Show links (optional)
655 * @param $wikilang The langauge of the wiki to display the list in, for the links (optional)
656 */
657 public function outputMessagesList( $messages, $code, $text = '', $level = 2, $links = false, $wikilang = null ) {
658 if ( count( $messages ) == 0 ) {
659 return;
660 }
661 if ( $text ) {
662 echo "$text\n";
663 }
664 if ( $level == 1 ) {
665 echo "[messages are hidden]\n";
666 } else {
667 foreach ( $messages as $key => $value ) {
668 if ( $links ) {
669 $displayKey = ucfirst( $key );
670 if ( !isset( $wikilang ) ) {
671 global $wgContLang;
672 $wikilang = $wgContLang->getCode();
673 }
674 if ( $code == $wikilang ) {
675 $displayKey = "[[MediaWiki:$displayKey|$key]]";
676 } else {
677 $displayKey = "[[MediaWiki:$displayKey/$code|$key]]";
678 }
679 } else {
680 $displayKey = $key;
681 }
682 if ( $level == 2 ) {
683 echo "* $displayKey\n";
684 } else {
685 echo "* $displayKey: '$value'\n";
686 }
687 }
688 }
689 }
690 }
691
692 ?>