MediaWikiMessageChecker.php

Go to the documentation of this file.
00001 <?php
00016 class MediaWikiMessageChecker extends MessageChecker {
00025     protected function wikiParameterCheck( $messages, $code, &$warnings ) {
00026         parent::parameterCheck( $messages, $code, $warnings, '/\$[1-9]/' );
00027     }
00028 
00039     protected function wikiLinksCheck( $messages, $code, &$warnings ) {
00040         $tc = Title::legalChars() . '#%{}';
00041 
00042         foreach ( $messages as $message ) {
00043             $key = $message->key();
00044             $definition = $message->definition();
00045             $translation = $message->translation();
00046 
00047             $subcheck = 'extra';
00048             $matches = $links = array();
00049             preg_match_all( "/\[\[([{$tc}]+)(\\|(.+?))?]]/sDu", $translation, $matches );
00050             $count = count( $matches[0] );
00051             for ( $i = 0; $i < $count; $i++ ) {
00052                 $backMatch = preg_quote( $matches[1][$i], '/' );
00053 
00054                 if ( preg_match( "/\[\[$backMatch/", $definition ) ) {
00055                     continue;
00056                 }
00057 
00058                 $links[] = "[[{$matches[1][$i]}{$matches[2][$i]}]]";
00059             }
00060 
00061             if ( count( $links ) ) {
00062                 $warnings[$key][] = array(
00063                     array( 'links', $subcheck, $key, $code ),
00064                     'translate-checks-links',
00065                     array( 'PARAMS', $links ),
00066                     array( 'COUNT', count( $links ) ),
00067                 );
00068             }
00069 
00070             $subcheck = 'missing';
00071             $matches = $links = array();
00072             preg_match_all( "/\[\[([{$tc}]+)(\\|(.+?))?]]/sDu", $definition, $matches );
00073             $count = count( $matches[0] );
00074             for ( $i = 0; $i < $count; $i++ ) {
00075                 $backMatch = preg_quote( $matches[1][$i], '/' );
00076 
00077                 if ( preg_match( "/\[\[$backMatch/", $translation ) ) {
00078                     continue;
00079                 }
00080 
00081                 $links[] = "[[{$matches[1][$i]}{$matches[2][$i]}]]";
00082             }
00083 
00084             if ( count( $links ) ) {
00085                 $warnings[$key][] = array(
00086                     array( 'links', $subcheck, $key, $code ),
00087                     'translate-checks-links-missing',
00088                     array( 'PARAMS', $links ),
00089                     array( 'COUNT', count( $links ) ),
00090                 );
00091             }
00092         }
00093     }
00094 
00102     protected function XhtmlCheck( $messages, $code, &$warnings ) {
00103         foreach ( $messages as $message ) {
00104             $key = $message->key();
00105             $translation = $message->translation();
00106             if ( strpos( $translation, '<' ) === false ) {
00107                 continue;
00108             }
00109 
00110             $subcheck = 'invalid';
00111             $tags = array(
00112                 '~<hr *(\\\\)?>~suDi' => '<hr />', // Wrong syntax
00113                 '~<br *(\\\\)?>~suDi' => '<br />',
00114                 '~<hr/>~suDi' => '<hr />', // Wrong syntax
00115                 '~<br/>~suDi' => '<br />',
00116                 '~<(HR|Hr|hR) />~su' => '<hr />', // Case
00117                 '~<(BR|Br|bR) />~su' => '<br />',
00118             );
00119 
00120             $wrongTags = array();
00121             foreach ( $tags as $wrong => $correct ) {
00122                 $matches = array();
00123                 preg_match_all( $wrong, $translation, $matches, PREG_PATTERN_ORDER );
00124                 foreach ( $matches[0] as $wrongMatch ) {
00125                     $wrongTags[$wrongMatch] = "$wrongMatch → $correct";
00126                 }
00127             }
00128 
00129             if ( count( $wrongTags ) ) {
00130                 $warnings[$key][] = array(
00131                     array( 'xhtml', $subcheck, $key, $code ),
00132                     'translate-checks-xhtml',
00133                     array( 'PARAMS', $wrongTags ),
00134                     array( 'COUNT', count( $wrongTags ) ),
00135                 );
00136             }
00137         }
00138     }
00139 
00147     protected function pluralCheck( $messages, $code, &$warnings ) {
00148         foreach ( $messages as $message ) {
00149             $key = $message->key();
00150             $definition = $message->definition();
00151             $translation = $message->translation();
00152 
00153             $subcheck = 'missing';
00154             if (
00155                 stripos( $definition, '{{plural:' ) !== false &&
00156                 stripos( $translation, '{{plural:' ) === false
00157             ) {
00158                 $warnings[$key][] = array(
00159                     array( 'plural', $subcheck, $key, $code ),
00160                     'translate-checks-plural',
00161                 );
00162             }
00163         }
00164     }
00165 
00173     protected function pluralFormsCheck( $messages, $code, &$warnings ) {
00174         foreach ( $messages as $message ) {
00175             $key = $message->key();
00176             $translation = $message->translation();
00177 
00178             // Does this version of MediaWiki support v1.20-style CLDR plural rules?
00179             if ( !method_exists( 'Language', 'getPluralRules' ) ) {
00180                 return;
00181             }
00182 
00183             // Are there any plural forms for this language in this message?
00184             if ( stripos( $translation, '{{plural:' ) === false ) {
00185                 return;
00186             }
00187 
00188             $plurals = self::getPluralForms( $translation );
00189             $allowed = self::getPluralFormCount( $code );
00190 
00191             foreach ( $plurals as $forms ) {
00192                 $forms = self::removeExplicitPluralForms( $forms );
00193                 $provided = count( $forms );
00194 
00195                 if ( $provided > $allowed ) {
00196                     $warnings[$key][] = array(
00197                         array( 'plural', 'forms', $key, $code ),
00198                         'translate-checks-plural-forms', $provided, $allowed
00199                     );
00200                 }
00201 
00202                 // Are the last two forms identical?
00203                 if ( $provided > 1 && $forms[$provided - 1] === $forms[$provided - 2] ) {
00204                     $warnings[$key][] = array(
00205                         array( 'plural', 'dupe', $key, $code ),
00206                         'translate-checks-plural-dupe'
00207                     );
00208                 }
00209             }
00210         }
00211     }
00212 
00220     public static function getPluralFormCount( $code ) {
00221         $forms = Language::factory( $code )->getPluralRules();
00222 
00223         // +1 for the 'other' form
00224         return count( $forms ) + 1;
00225     }
00226 
00235     public static function getPluralForms( $translation ) {
00236         $plurals = array();
00237         while ( true ) {
00238             $pos = stripos( $translation, '{{plural:' );
00239             if ( $pos === false ) {
00240                 break;
00241             }
00242 
00243             $len = strlen( $translation );
00244             $stack = 0;
00245             for ( $i = $pos; $i < $len; $i++ ) {
00246                 if ( $translation[$i] === '{' ) {
00247                     $stack++;
00248                 } elseif ( $translation[$i] === '}' ) {
00249                     $stack--;
00250                 } elseif ( $stack > 2 && $translation[$i] === '|' ) {
00251                     # These pipes belong to another thing, ignore them
00252                     $translation[$i] = '_';
00253                 }
00254 
00255                 if ( $stack === 0 ) {
00256                     // The string '{{PLURAL...' (without closing }})
00257                     $pluralString = substr( $translation, $pos, $i - $pos - 1 );
00258                     $forms = explode( '|', $pluralString );
00259                     array_shift( $forms );
00260 
00261                     // Remove this from the current string to continue later
00262                     $translation = substr( $translation, $i );
00263 
00264                     $plurals[] = $forms;
00265                     break;
00266                 }
00267             }
00268 
00269             // Unclosed plural, stop here
00270             if ( $i === $len ) {
00271                 break;
00272             }
00273         }
00274 
00275         return $plurals;
00276     }
00277 
00285     public static function removeExplicitPluralForms( array $forms ) {
00286         // Handle explicit 0= and 1= forms
00287         foreach ( $forms as $index => $form ) {
00288             if ( isset( $form[1] ) && $form[1] === '=' ) {
00289                 unset( $forms[$index] );
00290             }
00291         }
00292 
00293         return array_values( $forms );
00294     }
00295 
00303     protected function pagenameMessagesCheck( $messages, $code, &$warnings ) {
00304         foreach ( $messages as $message ) {
00305             $key = $message->key();
00306             $definition = $message->definition();
00307             $translation = $message->translation();
00308 
00309             $subcheck = 'namespace';
00310             $namespaces = 'help|project|\{\{ns:project}}|mediawiki';
00311             $matches = array();
00312             if ( preg_match( "/^($namespaces):[\w\s]+$/ui", $definition, $matches ) ) {
00313                 if ( !preg_match( "/^{$matches[1]}:.+$/u", $translation ) ) {
00314                     $warnings[$key][] = array(
00315                         array( 'pagename', $subcheck, $key, $code ),
00316                         'translate-checks-pagename',
00317                     );
00318                 }
00319             }
00320         }
00321     }
00322 
00330     protected function miscMWChecks( $messages, $code, &$warnings ) {
00331         $timeList = array( 'protect-expiry-options', 'ipboptions' );
00332 
00333         foreach ( $messages as $message ) {
00334             $key = $message->key();
00335             $definition = $message->definition();
00336             $translation = $message->translation();
00337 
00338             if ( in_array( strtolower( $key ), $timeList, true ) ) {
00339                 $defArray = explode( ',', $definition );
00340                 $traArray = explode( ',', $translation );
00341 
00342                 $subcheck = 'timelist-count';
00343                 $defCount = count( $defArray );
00344                 $traCount = count( $traArray );
00345                 if ( $defCount !== $traCount ) {
00346                     $warnings[$key][] = array(
00347                         array( 'miscmw', $subcheck, $key, $code ),
00348                         'translate-checks-format',
00349                         wfMessage( 'translate-checks-parametersnotequal' )
00350                             ->numParams( $traCount, $defCount )->text()
00351                     );
00352 
00353                     continue;
00354                 }
00355 
00356                 for ( $i = 0; $i < $defCount; $i++ ) {
00357                     $defItems = array_map( 'trim', explode( ':', $defArray[$i] ) );
00358                     $traItems = array_map( 'trim', explode( ':', $traArray[$i] ) );
00359 
00360                     $subcheck = 'timelist-format';
00361                     if ( count( $traItems ) !== 2 ) {
00362                         $warnings[$key][] = array(
00363                             array( 'miscmw', $subcheck, $key, $code ),
00364                             'translate-checks-format',
00365                             wfMessage(
00366                                 'translate-checks-malformed',
00367                                 $traArray[$i]
00368                             )->text()
00369                         );
00370                         continue;
00371                     }
00372 
00373                     $subcheck = 'timelist-format-value';
00374                     if ( $traItems[1] !== $defItems[1] ) {
00375                         $warnings[$key][] = array(
00376                             array( 'miscmw', $subcheck, $key, $code ),
00377                             'translate-checks-format',
00378                             "<samp><nowiki>$traItems[1] !== $defItems[1]</nowiki></samp>", // @todo FIXME: i18n missing.
00379                         );
00380                         continue;
00381                     }
00382                 }
00383             }
00384         }
00385     }
00386 }
Generated on Tue Oct 29 00:00:24 2013 for MediaWiki Translate Extension by  doxygen 1.6.3