Don't load all languages just to check whether message is known.
[mediawiki.git] / maintenance / language / languages.inc
blob60b1112fdfd801ad20a48012f2a2d88136e270fb
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 Treat the EXIF messages?
47          */
48         function __construct( $exif = true ) {
49                 require( dirname(__FILE__) . '/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::getLanguageNames( true ) );
58                 sort( $this->mLanguages );
59         }
61         /**
62          * Get the language list.
63          *
64          * @return The language list.
65          */
66         public function getLanguages() {
67                 return $this->mLanguages;
68         }
70         /**
71          * Get the ignored messages list.
72          *
73          * @return The ignored messages list.
74          */
75         public function getIgnoredMessages() {
76                 return $this->mIgnoredMessages;
77         }
79         /**
80          * Get the optional messages list.
81          *
82          * @return 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 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                         } else if ( 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                         } else if ( 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 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 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 The language code.
234          *
235          * @return 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 The language code.
246          *
247          * @return 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 The language code.
258          *
259          * @return 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 The language code.
270          *
271          * @return 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 The language code.
282          *
283          * @return 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 The language code.
294          *
295          * @return 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 The language code.
307          *
308          * @return 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 The language code.
326          *
327          * @return 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 The language code.
339          *
340          * @return 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 The language code.
370          *
371          * @return 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 The language code.
389          *
390          * @return 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 The language code.
408          *
409          * @return 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 The language code.
427          *
428          * @return 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 The language code.
455          *
456          * @return 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 The language code.
492          *
493          * @return 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 The language code.
521          *
522          * @return 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                         }
550                         
551                 }
552                 return $messages;
553         }
555         /**
556          * Get the untranslated namespace names.
557          *
558          * @param $code The language code.
559          *
560          * @return 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] ) ) unset( $namespacesDiff[NS_MAIN] );
567                 return $namespacesDiff;
568         }
570         /**
571          * Get the project talk namespace names with no $1.
572          *
573          * @param $code The language code.
574          *
575          * @return The problematic project talk namespaces in this language.
576          */
577         public function getProblematicProjectTalks( $code ) {
578                 $this->loadFile( $code );
579                 $namespaces = array();
581                 # Check default namespace name
582                 if( isset( $this->mNamespaceNames[$code][NS_PROJECT_TALK] ) ) {
583                         $default = $this->mNamespaceNames[$code][NS_PROJECT_TALK];
584                         if ( strpos( $default, '$1' ) === FALSE ) {
585                                 $namespaces[$default] = 'default';
586                         }
587                 }
589                 # Check namespace aliases
590                 foreach( $this->mNamespaceAliases[$code] as $key => $value ) {
591                         if ( $value == NS_PROJECT_TALK && strpos( $key, '$1' ) === FALSE ) {
592                                 $namespaces[$key] = '';
593                         }
594                 }
596                 return $namespaces;
597         }
599         /**
600          * Get the untranslated magic words.
601          *
602          * @param $code The language code.
603          *
604          * @return The untranslated magic words in this language.
605          */
606         public function getUntranslatedMagicWords( $code ) {
607                 $this->loadFile( 'en' );
608                 $this->loadFile( $code );
609                 $magicWords = array();
610                 foreach ( $this->mMagicWords['en'] as $key => $value ) {
611                         if ( !isset( $this->mMagicWords[$code][$key] ) ) {
612                                 $magicWords[$key] = $value[1];
613                         }
614                 }
615                 return $magicWords;
616         }
618         /**
619          * Get the obsolete magic words.
620          *
621          * @param $code The language code.
622          *
623          * @return The obsolete magic words in this language.
624          */
625         public function getObsoleteMagicWords( $code ) {
626                 $this->loadFile( 'en' );
627                 $this->loadFile( $code );
628                 $magicWords = array();
629                 foreach ( $this->mMagicWords[$code] as $key => $value ) {
630                         if ( !isset( $this->mMagicWords['en'][$key] ) ) {
631                                 $magicWords[$key] = $value[1];
632                         }
633                 }
634                 return $magicWords;
635         }
637         /**
638          * Get the magic words that override the original English magic word.
639          *
640          * @param $code The language code.
641          *
642          * @return The overriding magic words in this language.
643          */
644         public function getOverridingMagicWords( $code ) {
645                 $this->loadFile( 'en' );
646                 $this->loadFile( $code );
647                 $magicWords = array();
648                 foreach ( $this->mMagicWords[$code] as $key => $local ) {
649                         if ( !isset( $this->mMagicWords['en'][$key] ) ) {
650                                 # Unrecognized magic word
651                                 continue;
652                         }
653                         $en = $this->mMagicWords['en'][$key];
654                         array_shift( $local );
655                         array_shift( $en );
656                         foreach ( $en as $word ) {
657                                 if ( !in_array( $word, $local ) ) {
658                                         $magicWords[$key] = $word;
659                                         break;
660                                 }
661                         }
662                 }
663                 return $magicWords;
664         }
666         /**
667          * Get the magic words which do not match the case-sensitivity of the original words.
668          *
669          * @param $code The language code.
670          *
671          * @return The magic words whose case does not match in this language.
672          */
673         public function getCaseMismatchMagicWords( $code ) {
674                 $this->loadFile( 'en' );
675                 $this->loadFile( $code );
676                 $magicWords = array();
677                 foreach ( $this->mMagicWords[$code] as $key => $local ) {
678                         if ( !isset( $this->mMagicWords['en'][$key] ) ) {
679                                 # Unrecognized magic word
680                                 continue;
681                         }
682                         if ( $local[0] != $this->mMagicWords['en'][$key][0] ) {
683                                 $magicWords[$key] = $local[0];
684                         }
685                 }
686                 return $magicWords;
687         }
689         /**
690          * Get the untranslated special page names.
691          *
692          * @param $code The language code.
693          *
694          * @return The untranslated special page names in this language.
695          */
696         public function getUntraslatedSpecialPages( $code ) {
697                 $this->loadFile( 'en' );
698                 $this->loadFile( $code );
699                 $specialPageAliases = array();
700                 foreach ( $this->mSpecialPageAliases['en'] as $key => $value ) {
701                         if ( !isset( $this->mSpecialPageAliases[$code][$key] ) ) {
702                                 $specialPageAliases[$key] = $value[0];
703                         }
704                 }
705                 return $specialPageAliases;
706         }
708         /**
709          * Get the obsolete special page names.
710          *
711          * @param $code The language code.
712          *
713          * @return The obsolete special page names in this language.
714          */
715         public function getObsoleteSpecialPages( $code ) {
716                 $this->loadFile( 'en' );
717                 $this->loadFile( $code );
718                 $specialPageAliases = array();
719                 foreach ( $this->mSpecialPageAliases[$code] as $key => $value ) {
720                         if ( !isset( $this->mSpecialPageAliases['en'][$key] ) ) {
721                                 $specialPageAliases[$key] = $value[0];
722                         }
723                 }
724                 return $specialPageAliases;
725         }
728 class extensionLanguages extends languages {
729         private $mMessageGroup; # The message group
731         /**
732          * Load the messages group.
733          * @param $group The messages group.
734          */
735         function __construct( MessageGroup $group ) {
736                 $this->mMessageGroup = $group;
738                 $bools = $this->mMessageGroup->getBools();
739                 $this->mIgnoredMessages = $bools['ignored'];
740                 $this->mOptionalMessages = $bools['optional'];
741         }
743         /**
744          * Get the extension name.
745          *
746          * @return The extension name.
747          */
748         public function name() {
749                 return $this->mMessageGroup->getLabel();
750         }
752         /**
753          * Load the language file.
754          *
755          * @param $code The language code.
756          */
757         protected function loadFile( $code ) {
758                 if( !isset( $this->mRawMessages[$code] ) ) {
759                         $this->mRawMessages[$code] = $this->mMessageGroup->load( $code );
760                         if( empty( $this->mRawMessages[$code] ) ) {
761                                 $this->mRawMessages[$code] = array();
762                         }
763                 }
764         }