Merge "Add ss_active_users in SiteStats::isSane"
[mediawiki.git] / maintenance / language / languages.inc
blob6070f4ab7fcbd6062f0040f62c998eaf209aa17e
1 <?php
2 /**
3  * Handle messages in the language files.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  * http://www.gnu.org/copyleft/gpl.html
19  *
20  * @file
21  * @ingroup MaintenanceLanguage
22  */
24 /**
25  * @ingroup MaintenanceLanguage
26  */
27 class languages {
28         protected $mLanguages; # List of languages
30         protected $mRawMessages; # Raw list of the messages in each language
31         protected $mMessages; # Messages in each language (except for English), divided to groups
32         protected $mFallback; # Fallback language in each language
33         protected $mGeneralMessages; # General messages in English, divided to groups
34         protected $mIgnoredMessages; # All the messages which should be exist only in the English file
35         protected $mOptionalMessages; # All the messages which may be translated or not, depending on the language
37         protected $mNamespaceNames; # Namespace names
38         protected $mNamespaceAliases; # Namespace aliases
39         protected $mMagicWords; # Magic words
40         protected $mSpecialPageAliases; # Special page aliases
42         /**
43          * Load the list of languages: all the Messages*.php
44          * files in the languages directory.
45          *
46          * @param $exif bool Treat the Exif messages?
47          */
48         function __construct( $exif = true ) {
49                 require __DIR__ . '/messageTypes.inc';
50                 $this->mIgnoredMessages = $wgIgnoredMessages;
51                 if ( $exif ) {
52                         $this->mOptionalMessages = array_merge( $wgOptionalMessages );
53                 } else {
54                         $this->mOptionalMessages = array_merge( $wgOptionalMessages, $wgEXIFMessages );
55                 }
57                 $this->mLanguages = array_keys( Language::fetchLanguageNames( null, 'mwfile' ) );
58                 sort( $this->mLanguages );
59         }
61         /**
62          * Get the language list.
63          *
64          * @return array The language list.
65          */
66         public function getLanguages() {
67                 return $this->mLanguages;
68         }
70         /**
71          * Get the ignored messages list.
72          *
73          * @return array The ignored messages list.
74          */
75         public function getIgnoredMessages() {
76                 return $this->mIgnoredMessages;
77         }
79         /**
80          * Get the optional messages list.
81          *
82          * @return array The  optional messages list.
83          */
84         public function getOptionalMessages() {
85                 return $this->mOptionalMessages;
86         }
88         /**
89          * Load the language file.
90          *
91          * @param $code string The language code.
92          */
93         protected function loadFile( $code ) {
94                 if ( isset( $this->mRawMessages[$code] ) &&
95                         isset( $this->mFallback[$code] ) &&
96                         isset( $this->mNamespaceNames[$code] ) &&
97                         isset( $this->mNamespaceAliases[$code] ) &&
98                         isset( $this->mMagicWords[$code] ) &&
99                         isset( $this->mSpecialPageAliases[$code] ) ) {
100                         return;
101                 }
102                 $this->mRawMessages[$code] = array();
103                 $this->mFallback[$code] = '';
104                 $this->mNamespaceNames[$code] = array();
105                 $this->mNamespaceAliases[$code] = array();
106                 $this->mMagicWords[$code] = array();
107                 $this->mSpecialPageAliases[$code] = array();
108                 $filename = Language::getMessagesFileName( $code );
109                 if ( file_exists( $filename ) ) {
110                         require $filename;
111                         if ( isset( $messages ) ) {
112                                 $this->mRawMessages[$code] = $messages;
113                         }
114                         if ( isset( $fallback ) ) {
115                                 $this->mFallback[$code] = $fallback;
116                         }
117                         if ( isset( $namespaceNames ) ) {
118                                 $this->mNamespaceNames[$code] = $namespaceNames;
119                         }
120                         if ( isset( $namespaceAliases ) ) {
121                                 $this->mNamespaceAliases[$code] = $namespaceAliases;
122                         }
123                         if ( isset( $magicWords ) ) {
124                                 $this->mMagicWords[$code] = $magicWords;
125                         }
126                         if ( isset( $specialPageAliases ) ) {
127                                 $this->mSpecialPageAliases[$code] = $specialPageAliases;
128                         }
129                 }
130         }
132         /**
133          * Load the messages for a specific language (which is not English) and divide them to groups:
134          * all - all the messages.
135          * required - messages which should be translated in order to get a complete translation.
136          * optional - messages which can be translated, the fallback translation is used if not translated.
137          * obsolete - messages which should not be translated, either because they do not exist, or they are ignored messages.
138          * translated - messages which are either required or optional, but translated from English and needed.
139          *
140          * @param $code string The language code.
141          */
142         private function loadMessages( $code ) {
143                 if ( isset( $this->mMessages[$code] ) ) {
144                         return;
145                 }
146                 $this->loadFile( $code );
147                 $this->loadGeneralMessages();
148                 $this->mMessages[$code]['all'] = $this->mRawMessages[$code];
149                 $this->mMessages[$code]['required'] = array();
150                 $this->mMessages[$code]['optional'] = array();
151                 $this->mMessages[$code]['obsolete'] = array();
152                 $this->mMessages[$code]['translated'] = array();
153                 foreach ( $this->mMessages[$code]['all'] as $key => $value ) {
154                         if ( isset( $this->mGeneralMessages['required'][$key] ) ) {
155                                 $this->mMessages[$code]['required'][$key] = $value;
156                                 $this->mMessages[$code]['translated'][$key] = $value;
157                         } elseif ( isset( $this->mGeneralMessages['optional'][$key] ) ) {
158                                 $this->mMessages[$code]['optional'][$key] = $value;
159                                 $this->mMessages[$code]['translated'][$key] = $value;
160                         } else {
161                                 $this->mMessages[$code]['obsolete'][$key] = $value;
162                         }
163                 }
164         }
166         /**
167          * Load the messages for English and divide them to groups:
168          * all - all the messages.
169          * required - messages which should be translated to other languages in order to get a complete translation.
170          * optional - messages which can be translated to other languages, but it's not required for a complete translation.
171          * ignored - messages which should not be translated to other languages.
172          * translatable - messages which are either required or optional, but can be translated from English.
173          */
174         private function loadGeneralMessages() {
175                 if ( isset( $this->mGeneralMessages ) ) {
176                         return;
177                 }
178                 $this->loadFile( 'en' );
179                 $this->mGeneralMessages['all'] = $this->mRawMessages['en'];
180                 $this->mGeneralMessages['required'] = array();
181                 $this->mGeneralMessages['optional'] = array();
182                 $this->mGeneralMessages['ignored'] = array();
183                 $this->mGeneralMessages['translatable'] = array();
184                 foreach ( $this->mGeneralMessages['all'] as $key => $value ) {
185                         if ( in_array( $key, $this->mIgnoredMessages ) ) {
186                                 $this->mGeneralMessages['ignored'][$key] = $value;
187                         } elseif ( in_array( $key, $this->mOptionalMessages ) ) {
188                                 $this->mGeneralMessages['optional'][$key] = $value;
189                                 $this->mGeneralMessages['translatable'][$key] = $value;
190                         } else {
191                                 $this->mGeneralMessages['required'][$key] = $value;
192                                 $this->mGeneralMessages['translatable'][$key] = $value;
193                         }
194                 }
195         }
197         /**
198          * Get all the messages for a specific language (not English), without the
199          * fallback language messages, divided to groups:
200          * all - all the messages.
201          * required - messages which should be translated in order to get a complete translation.
202          * optional - messages which can be translated, the fallback translation is used if not translated.
203          * obsolete - messages which should not be translated, either because they do not exist, or they are ignored messages.
204          * translated - messages which are either required or optional, but translated from English and needed.
205          *
206          * @param $code string The language code.
207          *
208          * @return string The messages in this language.
209          */
210         public function getMessages( $code ) {
211                 $this->loadMessages( $code );
212                 return $this->mMessages[$code];
213         }
215         /**
216          * Get all the general English messages, divided to groups:
217          * all - all the messages.
218          * required - messages which should be translated to other languages in order to get a complete translation.
219          * optional - messages which can be translated to other languages, but it's not required for a complete translation.
220          * ignored - messages which should not be translated to other languages.
221          * translatable - messages which are either required or optional, but can be translated from English.
222          *
223          * @return array The general English messages.
224          */
225         public function getGeneralMessages() {
226                 $this->loadGeneralMessages();
227                 return $this->mGeneralMessages;
228         }
230         /**
231          * Get fallback language code for a specific language.
232          *
233          * @param $code string The language code.
234          *
235          * @return string Fallback code.
236          */
237         public function getFallback( $code ) {
238                 $this->loadFile( $code );
239                 return $this->mFallback[$code];
240         }
242         /**
243          * Get namespace names for a specific language.
244          *
245          * @param $code string The language code.
246          *
247          * @return array Namespace names.
248          */
249         public function getNamespaceNames( $code ) {
250                 $this->loadFile( $code );
251                 return $this->mNamespaceNames[$code];
252         }
254         /**
255          * Get namespace aliases for a specific language.
256          *
257          * @param $code string The language code.
258          *
259          * @return array Namespace aliases.
260          */
261         public function getNamespaceAliases( $code ) {
262                 $this->loadFile( $code );
263                 return $this->mNamespaceAliases[$code];
264         }
266         /**
267          * Get magic words for a specific language.
268          *
269          * @param $code string The language code.
270          *
271          * @return array Magic words.
272          */
273         public function getMagicWords( $code ) {
274                 $this->loadFile( $code );
275                 return $this->mMagicWords[$code];
276         }
278         /**
279          * Get special page aliases for a specific language.
280          *
281          * @param $code string The language code.
282          *
283          * @return array Special page aliases.
284          */
285         public function getSpecialPageAliases( $code ) {
286                 $this->loadFile( $code );
287                 return $this->mSpecialPageAliases[$code];
288         }
290         /**
291          * Get the untranslated messages for a specific language.
292          *
293          * @param $code string The language code.
294          *
295          * @return array The untranslated messages for this language.
296          */
297         public function getUntranslatedMessages( $code ) {
298                 $this->loadGeneralMessages();
299                 $this->loadMessages( $code );
300                 return array_diff_key( $this->mGeneralMessages['required'], $this->mMessages[$code]['required'] );
301         }
303         /**
304          * Get the duplicate messages for a specific language.
305          *
306          * @param $code string The language code.
307          *
308          * @return array The duplicate messages for this language.
309          */
310         public function getDuplicateMessages( $code ) {
311                 $this->loadGeneralMessages();
312                 $this->loadMessages( $code );
313                 $duplicateMessages = array();
314                 foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
315                         if ( $this->mGeneralMessages['translatable'][$key] == $value ) {
316                                 $duplicateMessages[$key] = $value;
317                         }
318                 }
319                 return $duplicateMessages;
320         }
322         /**
323          * Get the obsolete messages for a specific language.
324          *
325          * @param $code string The language code.
326          *
327          * @return array The obsolete messages for this language.
328          */
329         public function getObsoleteMessages( $code ) {
330                 $this->loadGeneralMessages();
331                 $this->loadMessages( $code );
332                 return $this->mMessages[$code]['obsolete'];
333         }
335         /**
336          * Get the messages whose variables do not match the original ones.
337          *
338          * @param $code string The language code.
339          *
340          * @return array The messages whose variables do not match the original ones.
341          */
342         public function getMessagesWithMismatchVariables( $code ) {
343                 $this->loadGeneralMessages();
344                 $this->loadMessages( $code );
345                 $variables = array( '\$1', '\$2', '\$3', '\$4', '\$5', '\$6', '\$7', '\$8', '\$9' );
346                 $mismatchMessages = array();
347                 foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
348                         $missing = false;
349                         foreach ( $variables as $var ) {
350                                 if ( preg_match( "/$var/sU", $this->mGeneralMessages['translatable'][$key] ) &&
351                                         !preg_match( "/$var/sU", $value ) ) {
352                                         $missing = true;
353                                 }
354                                 if ( !preg_match( "/$var/sU", $this->mGeneralMessages['translatable'][$key] ) &&
355                                         preg_match( "/$var/sU", $value ) ) {
356                                         $missing = true;
357                                 }
358                         }
359                         if ( $missing ) {
360                                 $mismatchMessages[$key] = $value;
361                         }
362                 }
363                 return $mismatchMessages;
364         }
366         /**
367          * Get the messages which do not use plural.
368          *
369          * @param $code string The language code.
370          *
371          * @return array The messages which do not use plural in this language.
372          */
373         public function getMessagesWithoutPlural( $code ) {
374                 $this->loadGeneralMessages();
375                 $this->loadMessages( $code );
376                 $messagesWithoutPlural = array();
377                 foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
378                         if ( stripos( $this->mGeneralMessages['translatable'][$key], '{{plural:' ) !== false && stripos( $value, '{{plural:' ) === false ) {
379                                 $messagesWithoutPlural[$key] = $value;
380                         }
381                 }
382                 return $messagesWithoutPlural;
383         }
385         /**
386          * Get the empty messages.
387          *
388          * @param $code string The language code.
389          *
390          * @return array The empty messages for this language.
391          */
392         public function getEmptyMessages( $code ) {
393                 $this->loadGeneralMessages();
394                 $this->loadMessages( $code );
395                 $emptyMessages = array();
396                 foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
397                         if ( $value === '' || $value === '-' ) {
398                                 $emptyMessages[$key] = $value;
399                         }
400                 }
401                 return $emptyMessages;
402         }
404         /**
405          * Get the messages with trailing whitespace.
406          *
407          * @param $code string The language code.
408          *
409          * @return array The messages with trailing whitespace in this language.
410          */
411         public function getMessagesWithWhitespace( $code ) {
412                 $this->loadGeneralMessages();
413                 $this->loadMessages( $code );
414                 $messagesWithWhitespace = array();
415                 foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
416                         if ( $this->mGeneralMessages['translatable'][$key] !== '' && $value !== rtrim( $value ) ) {
417                                 $messagesWithWhitespace[$key] = $value;
418                         }
419                 }
420                 return $messagesWithWhitespace;
421         }
423         /**
424          * Get the non-XHTML messages.
425          *
426          * @param $code string The language code.
427          *
428          * @return array The non-XHTML messages for this language.
429          */
430         public function getNonXHTMLMessages( $code ) {
431                 $this->loadGeneralMessages();
432                 $this->loadMessages( $code );
433                 $wrongPhrases = array(
434                         '<hr *\\?>',
435                         '<br *\\?>',
436                         '<hr/>',
437                         '<br/>',
438                         '<hr>',
439                         '<br>',
440                 );
441                 $wrongPhrases = '~(' . implode( '|', $wrongPhrases ) . ')~sDu';
442                 $nonXHTMLMessages = array();
443                 foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
444                         if ( preg_match( $wrongPhrases, $value ) ) {
445                                 $nonXHTMLMessages[$key] = $value;
446                         }
447                 }
448                 return $nonXHTMLMessages;
449         }
451         /**
452          * Get the messages which include wrong characters.
453          *
454          * @param $code string The language code.
455          *
456          * @return array The messages which include wrong characters in this language.
457          */
458         public function getMessagesWithWrongChars( $code ) {
459                 $this->loadGeneralMessages();
460                 $this->loadMessages( $code );
461                 $wrongChars = array(
462                         '[LRM]' => "\xE2\x80\x8E",
463                         '[RLM]' => "\xE2\x80\x8F",
464                         '[LRE]' => "\xE2\x80\xAA",
465                         '[RLE]' => "\xE2\x80\xAB",
466                         '[POP]' => "\xE2\x80\xAC",
467                         '[LRO]' => "\xE2\x80\xAD",
468                         '[RLO]' => "\xE2\x80\xAB",
469                         '[ZWSP]' => "\xE2\x80\x8B",
470                         '[NBSP]' => "\xC2\xA0",
471                         '[WJ]' => "\xE2\x81\xA0",
472                         '[BOM]' => "\xEF\xBB\xBF",
473                         '[FFFD]' => "\xEF\xBF\xBD",
474                 );
475                 $wrongRegExp = '/(' . implode( '|', array_values( $wrongChars ) ) . ')/sDu';
476                 $wrongCharsMessages = array();
477                 foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
478                         if ( preg_match( $wrongRegExp, $value ) ) {
479                                 foreach ( $wrongChars as $viewableChar => $hiddenChar ) {
480                                         $value = str_replace( $hiddenChar, $viewableChar, $value );
481                                 }
482                                 $wrongCharsMessages[$key] = $value;
483                         }
484                 }
485                 return $wrongCharsMessages;
486         }
488         /**
489          * Get the messages which include dubious links.
490          *
491          * @param $code string The language code.
492          *
493          * @return array The messages which include dubious links in this language.
494          */
495         public function getMessagesWithDubiousLinks( $code ) {
496                 $this->loadGeneralMessages();
497                 $this->loadMessages( $code );
498                 $tc = Title::legalChars() . '#%{}';
499                 $messages = array();
500                 foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
501                         $matches = array();
502                         preg_match_all( "/\[\[([{$tc}]+)(?:\\|(.+?))?]]/sDu", $value, $matches );
503                         for ( $i = 0; $i < count( $matches[0] ); $i++ ) {
504                                 if ( preg_match( "/.*project.*/isDu", $matches[1][$i] ) ) {
505                                         $messages[$key][] = $matches[0][$i];
506                                 }
507                         }
510                         if ( isset( $messages[$key] ) ) {
511                                 $messages[$key] = implode( $messages[$key], ", " );
512                         }
513                 }
514                 return $messages;
515         }
517         /**
518          * Get the messages which include unbalanced brackets.
519          *
520          * @param $code string The language code.
521          *
522          * @return array The messages which include unbalanced brackets in this language.
523          */
524         public function getMessagesWithUnbalanced( $code ) {
525                 $this->loadGeneralMessages();
526                 $this->loadMessages( $code );
527                 $messages = array();
528                 foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
529                         $a = $b = $c = $d = 0;
530                         foreach ( preg_split( '//', $value ) as $char ) {
531                                 switch ( $char ) {
532                                         case '[':
533                                                 $a++;
534                                                 break;
535                                         case ']':
536                                                 $b++;
537                                                 break;
538                                         case '{':
539                                                 $c++;
540                                                 break;
541                                         case '}':
542                                                 $d++;
543                                                 break;
544                                 }
545                         }
547                         if ( $a !== $b || $c !== $d ) {
548                                 $messages[$key] = "$a, $b, $c, $d";
549                         }
551                 }
552                 return $messages;
553         }
555         /**
556          * Get the untranslated namespace names.
557          *
558          * @param $code string The language code.
559          *
560          * @return array The untranslated namespace names in this language.
561          */
562         public function getUntranslatedNamespaces( $code ) {
563                 $this->loadFile( 'en' );
564                 $this->loadFile( $code );
565                 $namespacesDiff = array_diff_key( $this->mNamespaceNames['en'], $this->mNamespaceNames[$code] );
566                 if ( isset( $namespacesDiff[NS_MAIN] ) ) {
567                         unset( $namespacesDiff[NS_MAIN] );
568                 }
569                 return $namespacesDiff;
570         }
572         /**
573          * Get the project talk namespace names with no $1.
574          *
575          * @param $code string The language code.
576          *
577          * @return array The problematic project talk namespaces in this language.
578          */
579         public function getProblematicProjectTalks( $code ) {
580                 $this->loadFile( $code );
581                 $namespaces = array();
583                 # Check default namespace name
584                 if ( isset( $this->mNamespaceNames[$code][NS_PROJECT_TALK] ) ) {
585                         $default = $this->mNamespaceNames[$code][NS_PROJECT_TALK];
586                         if ( strpos( $default, '$1' ) === false ) {
587                                 $namespaces[$default] = 'default';
588                         }
589                 }
591                 # Check namespace aliases
592                 foreach ( $this->mNamespaceAliases[$code] as $key => $value ) {
593                         if ( $value == NS_PROJECT_TALK && strpos( $key, '$1' ) === false ) {
594                                 $namespaces[$key] = '';
595                         }
596                 }
598                 return $namespaces;
599         }
601         /**
602          * Get the untranslated magic words.
603          *
604          * @param $code string The language code.
605          *
606          * @return array The untranslated magic words in this language.
607          */
608         public function getUntranslatedMagicWords( $code ) {
609                 $this->loadFile( 'en' );
610                 $this->loadFile( $code );
611                 $magicWords = array();
612                 foreach ( $this->mMagicWords['en'] as $key => $value ) {
613                         if ( !isset( $this->mMagicWords[$code][$key] ) ) {
614                                 $magicWords[$key] = $value[1];
615                         }
616                 }
617                 return $magicWords;
618         }
620         /**
621          * Get the obsolete magic words.
622          *
623          * @param $code string The language code.
624          *
625          * @return array The obsolete magic words in this language.
626          */
627         public function getObsoleteMagicWords( $code ) {
628                 $this->loadFile( 'en' );
629                 $this->loadFile( $code );
630                 $magicWords = array();
631                 foreach ( $this->mMagicWords[$code] as $key => $value ) {
632                         if ( !isset( $this->mMagicWords['en'][$key] ) ) {
633                                 $magicWords[$key] = $value[1];
634                         }
635                 }
636                 return $magicWords;
637         }
639         /**
640          * Get the magic words that override the original English magic word.
641          *
642          * @param $code string The language code.
643          *
644          * @return array The overriding magic words in this language.
645          */
646         public function getOverridingMagicWords( $code ) {
647                 $this->loadFile( 'en' );
648                 $this->loadFile( $code );
649                 $magicWords = array();
650                 foreach ( $this->mMagicWords[$code] as $key => $local ) {
651                         if ( !isset( $this->mMagicWords['en'][$key] ) ) {
652                                 # Unrecognized magic word
653                                 continue;
654                         }
655                         $en = $this->mMagicWords['en'][$key];
656                         array_shift( $local );
657                         array_shift( $en );
658                         foreach ( $en as $word ) {
659                                 if ( !in_array( $word, $local ) ) {
660                                         $magicWords[$key] = $word;
661                                         break;
662                                 }
663                         }
664                 }
665                 return $magicWords;
666         }
668         /**
669          * Get the magic words which do not match the case-sensitivity of the original words.
670          *
671          * @param $code string The language code.
672          *
673          * @return array The magic words whose case does not match in this language.
674          */
675         public function getCaseMismatchMagicWords( $code ) {
676                 $this->loadFile( 'en' );
677                 $this->loadFile( $code );
678                 $magicWords = array();
679                 foreach ( $this->mMagicWords[$code] as $key => $local ) {
680                         if ( !isset( $this->mMagicWords['en'][$key] ) ) {
681                                 # Unrecognized magic word
682                                 continue;
683                         }
684                         if ( $local[0] != $this->mMagicWords['en'][$key][0] ) {
685                                 $magicWords[$key] = $local[0];
686                         }
687                 }
688                 return $magicWords;
689         }
691         /**
692          * Get the untranslated special page names.
693          *
694          * @param $code string The language code.
695          *
696          * @return array The untranslated special page names in this language.
697          */
698         public function getUntraslatedSpecialPages( $code ) {
699                 $this->loadFile( 'en' );
700                 $this->loadFile( $code );
701                 $specialPageAliases = array();
702                 foreach ( $this->mSpecialPageAliases['en'] as $key => $value ) {
703                         if ( !isset( $this->mSpecialPageAliases[$code][$key] ) ) {
704                                 $specialPageAliases[$key] = $value[0];
705                         }
706                 }
707                 return $specialPageAliases;
708         }
710         /**
711          * Get the obsolete special page names.
712          *
713          * @param $code string The language code.
714          *
715          * @return array The obsolete special page names in this language.
716          */
717         public function getObsoleteSpecialPages( $code ) {
718                 $this->loadFile( 'en' );
719                 $this->loadFile( $code );
720                 $specialPageAliases = array();
721                 foreach ( $this->mSpecialPageAliases[$code] as $key => $value ) {
722                         if ( !isset( $this->mSpecialPageAliases['en'][$key] ) ) {
723                                 $specialPageAliases[$key] = $value[0];
724                         }
725                 }
726                 return $specialPageAliases;
727         }
730 class extensionLanguages extends languages {
732         /**
733          * @var MessageGroup
734          */
735         private $mMessageGroup;
737         /**
738          * Load the messages group.
739          * @param $group MessageGroup The messages group.
740          */
741         function __construct( MessageGroup $group ) {
742                 $this->mMessageGroup = $group;
744                 $this->mIgnoredMessages = $this->mMessageGroup->getIgnored();
745                 $this->mOptionalMessages = $this->mMessageGroup->getOptional();
746         }
748         /**
749          * Get the extension name.
750          *
751          * @return string The extension name.
752          */
753         public function name() {
754                 return $this->mMessageGroup->getLabel();
755         }
757         /**
758          * Load the language file.
759          *
760          * @param $code string The language code.
761          */
762         protected function loadFile( $code ) {
763                 if ( !isset( $this->mRawMessages[$code] ) ) {
764                         $this->mRawMessages[$code] = $this->mMessageGroup->load( $code );
765                         if ( empty( $this->mRawMessages[$code] ) ) {
766                                 $this->mRawMessages[$code] = array();
767                         }
768                 }
769         }