Index: branches/nikola/phase3/languages/LanguageConverter.php |
— | — | @@ -67,12 +67,12 @@ |
68 | 68 | public function __construct( $langobj, $maincode, $variants = array(), |
69 | 69 | $variantfallbacks = array(), $flags = array(), |
70 | 70 | $manualLevel = array() ) { |
71 | | - global $wgDisabledVariants, $wgLanguageNames; |
| 71 | + global $wgDisabledVariants; |
72 | 72 | $this->mLangObj = $langobj; |
73 | 73 | $this->mMainLanguageCode = $maincode; |
74 | 74 | $this->mVariants = array_diff( $variants, $wgDisabledVariants ); |
75 | 75 | $this->mVariantFallbacks = $variantfallbacks; |
76 | | - $this->mVariantNames = $wgLanguageNames; |
| 76 | + $this->mVariantNames = Language::fetchLanguageNames(); |
77 | 77 | $this->mCacheKey = wfMemcKey( 'conversiontables', $maincode ); |
78 | 78 | $defaultflags = array( |
79 | 79 | // 'S' show converted text |
— | — | @@ -117,7 +117,7 @@ |
118 | 118 | * in this case. Right now this is only used by zh. |
119 | 119 | * |
120 | 120 | * @param $variant String: the language code of the variant |
121 | | - * @return String: The code of the fallback language or the |
| 121 | + * @return String|array: The code of the fallback language or the |
122 | 122 | * main code if there is no fallback |
123 | 123 | */ |
124 | 124 | public function getVariantFallbacks( $variant ) { |
— | — | @@ -158,7 +158,7 @@ |
159 | 159 | // not memoized (i.e. there return value is not cached) since |
160 | 160 | // new information might appear during processing after this |
161 | 161 | // is first called. |
162 | | - if ( $req ) { |
| 162 | + if ( $this->validateVariant( $req ) ) { |
163 | 163 | return $req; |
164 | 164 | } |
165 | 165 | return $this->mMainLanguageCode; |
— | — | @@ -189,7 +189,7 @@ |
190 | 190 | * @param $variant String: the variant to validate |
191 | 191 | * @return Mixed: returns the variant if it is valid, null otherwise |
192 | 192 | */ |
193 | | - protected function validateVariant( $variant = null ) { |
| 193 | + public function validateVariant( $variant = null ) { |
194 | 194 | if ( $variant !== null && in_array( $variant, $this->mVariants ) ) { |
195 | 195 | return $variant; |
196 | 196 | } |
— | — | @@ -305,9 +305,9 @@ |
306 | 306 | * If you want to parse rules, try to use convert() or |
307 | 307 | * convertTo(). |
308 | 308 | * |
309 | | - * @param $text String: the text to be converted |
310 | | - * @param $toVariant String: the target language code |
311 | | - * @return String: the converted text |
| 309 | + * @param $text String the text to be converted |
| 310 | + * @param $toVariant bool|string the target language code |
| 311 | + * @return String the converted text |
312 | 312 | */ |
313 | 313 | public function autoConvert( $text, $toVariant = false ) { |
314 | 314 | wfProfileIn( __METHOD__ ); |
— | — | @@ -323,6 +323,7 @@ |
324 | 324 | } |
325 | 325 | |
326 | 326 | if( $this->guessVariant( $text, $toVariant ) ) { |
| 327 | + wfProfileOut( __METHOD__ ); |
327 | 328 | return $text; |
328 | 329 | } |
329 | 330 | |
— | — | @@ -372,11 +373,11 @@ |
373 | 374 | $sourceBlob .= substr( $text, $startPos, $elementPos - $startPos ) . "\000"; |
374 | 375 | |
375 | 376 | // Advance to the next position |
376 | | - $startPos = $elementPos + strlen( $element ); |
| 377 | + $startPos = $elementPos + strlen( $element ); |
377 | 378 | |
378 | 379 | // Translate any alt or title attributes inside the matched element |
379 | | - if ( $element !== '' && preg_match( '/^(<[^>\s]*)\s([^>]*)(.*)$/', $element, |
380 | | - $elementMatches ) ) |
| 380 | + if ( $element !== '' && preg_match( '/^(<[^>\s]*)\s([^>]*)(.*)$/', $element, |
| 381 | + $elementMatches ) ) |
381 | 382 | { |
382 | 383 | $attrs = Sanitizer::decodeTagAttributes( $elementMatches[2] ); |
383 | 384 | $changed = false; |
— | — | @@ -389,7 +390,7 @@ |
390 | 391 | if ( !strpos( $attr, '://' ) ) { |
391 | 392 | $attr = $this->translate( $attr, $toVariant ); |
392 | 393 | } |
393 | | - |
| 394 | + |
394 | 395 | // Remove HTML tags to avoid disrupting the layout |
395 | 396 | $attr = preg_replace( '/<[^>]+>/', '', $attr ); |
396 | 397 | if ( $attr !== $attrs[$attrName] ) { |
— | — | @@ -398,7 +399,7 @@ |
399 | 400 | } |
400 | 401 | } |
401 | 402 | if ( $changed ) { |
402 | | - $element = $elementMatches[1] . Html::expandAttributes( $attrs ) . |
| 403 | + $element = $elementMatches[1] . Html::expandAttributes( $attrs ) . |
403 | 404 | $elementMatches[3]; |
404 | 405 | } |
405 | 406 | } |
— | — | @@ -472,7 +473,7 @@ |
473 | 474 | * |
474 | 475 | * @param $text String: the text to be converted |
475 | 476 | * @return Array: variant => converted text |
476 | | - * @deprecated Use autoConvertToAllVariants() instead |
| 477 | + * @deprecated since 1.17 Use autoConvertToAllVariants() instead |
477 | 478 | */ |
478 | 479 | public function convertLinkToAllVariants( $text ) { |
479 | 480 | return $this->autoConvertToAllVariants( $text ); |
— | — | @@ -481,7 +482,7 @@ |
482 | 483 | /** |
483 | 484 | * Apply manual conversion rules. |
484 | 485 | * |
485 | | - * @param $convRule Object: Object of ConverterRule |
| 486 | + * @param $convRule ConverterRule Object of ConverterRule |
486 | 487 | */ |
487 | 488 | protected function applyManualConv( $convRule ) { |
488 | 489 | // Use syntax -{T|zh-cn:TitleCN; zh-tw:TitleTw}- to custom |
— | — | @@ -521,7 +522,7 @@ |
522 | 523 | * Auto convert a Title object to a readable string in the |
523 | 524 | * preferred variant. |
524 | 525 | * |
525 | | - * @param $title Object: a object of Title |
| 526 | + * @param $title Title a object of Title |
526 | 527 | * @return String: converted title text |
527 | 528 | */ |
528 | 529 | public function convertTitle( $title ) { |
— | — | @@ -531,9 +532,9 @@ |
532 | 533 | $text = ''; |
533 | 534 | } else { |
534 | 535 | // first let's check if a message has given us a converted name |
535 | | - $nsConvKey = 'conversion-ns' . $index; |
536 | | - if ( !wfEmptyMsg( $nsConvKey ) ) { |
537 | | - $text = wfMsgForContentNoTrans( $nsConvKey ); |
| 536 | + $nsConvMsg = wfMessage( 'conversion-ns' . $index )->inContentLanguage(); |
| 537 | + if ( $nsConvMsg->exists() ) { |
| 538 | + $text = $nsConvMsg->plain(); |
538 | 539 | } else { |
539 | 540 | // the message does not exist, try retrieve it from the current |
540 | 541 | // variant's namespace names. |
— | — | @@ -622,7 +623,10 @@ |
623 | 624 | * |
624 | 625 | * @param $text String: text to be converted |
625 | 626 | * @param $variant String: the target variant code |
| 627 | + * @param $startPos int |
626 | 628 | * @param $depth Integer: depth of recursion |
| 629 | + * |
| 630 | + * @throws MWException |
627 | 631 | * @return String: converted text |
628 | 632 | */ |
629 | 633 | protected function recursiveConvertRule( $text, $variant, &$startPos, $depth = 0 ) { |
— | — | @@ -766,6 +770,8 @@ |
767 | 771 | |
768 | 772 | /** |
769 | 773 | * Returns language specific hash options. |
| 774 | + * |
| 775 | + * @return string |
770 | 776 | */ |
771 | 777 | public function getExtraHashOptions() { |
772 | 778 | $variant = $this->getPreferredVariant(); |
— | — | @@ -780,7 +786,7 @@ |
781 | 787 | * @return bool true if $text appears to be written in $variant, false if not |
782 | 788 | * |
783 | 789 | * @author Nikola Smolenski <smolensk@eunet.rs> |
784 | | - * @since 1.18 |
| 790 | + * @since 1.19 |
785 | 791 | */ |
786 | 792 | public function guessVariant($text, $variant) { |
787 | 793 | return false; |
— | — | @@ -791,10 +797,11 @@ |
792 | 798 | * This method must be implemented in derived class. |
793 | 799 | * |
794 | 800 | * @private |
| 801 | + * @throws MWException |
795 | 802 | */ |
796 | 803 | function loadDefaultTables() { |
797 | 804 | $name = get_class( $this ); |
798 | | - wfDie( "Must implement loadDefaultTables() method in class $name" ); |
| 805 | + throw new MWException( "Must implement loadDefaultTables() method in class $name" ); |
799 | 806 | } |
800 | 807 | |
801 | 808 | /** |
— | — | @@ -870,6 +877,8 @@ |
871 | 878 | * @param $code String: language code |
872 | 879 | * @param $subpage String: subpage name |
873 | 880 | * @param $recursive Boolean: parse subpages recursively? Defaults to true. |
| 881 | + * |
| 882 | + * @return array |
874 | 883 | */ |
875 | 884 | function parseCachedTable( $code, $subpage = '', $recursive = true ) { |
876 | 885 | static $parsed = array(); |
— | — | @@ -882,26 +891,26 @@ |
883 | 892 | return array(); |
884 | 893 | } |
885 | 894 | |
886 | | - if ( strpos( $code, '/' ) === false ) { |
887 | | - $txt = MessageCache::singleton()->get( 'Conversiontable', true, $code ); |
888 | | - if ( $txt === false ) { |
889 | | - # FIXME: this method doesn't seem to be expecting |
890 | | - # this possible outcome... |
891 | | - $txt = '<Conversiontable>'; |
892 | | - } |
| 895 | + $parsed[$key] = true; |
| 896 | + |
| 897 | + if ( $subpage === '' ) { |
| 898 | + $txt = MessageCache::singleton()->get( 'conversiontable', true, $code ); |
893 | 899 | } else { |
894 | | - $title = Title::makeTitleSafe( |
895 | | - NS_MEDIAWIKI, |
896 | | - "Conversiontable/$code" |
897 | | - ); |
| 900 | + $txt = false; |
| 901 | + $title = Title::makeTitleSafe( NS_MEDIAWIKI, $key ); |
898 | 902 | if ( $title && $title->exists() ) { |
899 | | - $article = new Article( $title ); |
900 | | - $txt = $article->getContents(); |
901 | | - } else { |
902 | | - $txt = ''; |
| 903 | + $revision = Revision::newFromTitle( $title ); |
| 904 | + if ( $revision ) { |
| 905 | + $txt = $revision->getRawText(); |
| 906 | + } |
903 | 907 | } |
904 | 908 | } |
905 | 909 | |
| 910 | + # Nothing to parse if there's no text |
| 911 | + if ( $txt === false || $txt === null || $txt === '' ) { |
| 912 | + return array(); |
| 913 | + } |
| 914 | + |
906 | 915 | // get all subpage links of the form |
907 | 916 | // [[MediaWiki:Conversiontable/zh-xx/...|...]] |
908 | 917 | $linkhead = $this->mLangObj->getNsText( NS_MEDIAWIKI ) . |
— | — | @@ -950,7 +959,6 @@ |
951 | 960 | $ret[trim( $m[0] )] = trim( $tt[0] ); |
952 | 961 | } |
953 | 962 | } |
954 | | - $parsed[$key] = true; |
955 | 963 | |
956 | 964 | // recursively parse the subpages |
957 | 965 | if ( $recursive ) { |
— | — | @@ -989,6 +997,10 @@ |
990 | 998 | /** |
991 | 999 | * Convert the sorting key for category links. This should make different |
992 | 1000 | * keys that are variants of each other map to the same key. |
| 1001 | + * |
| 1002 | + * @param $key string |
| 1003 | + * |
| 1004 | + * @return string |
993 | 1005 | */ |
994 | 1006 | function convertCategoryKey( $key ) { |
995 | 1007 | return $key; |
— | — | @@ -999,14 +1011,14 @@ |
1000 | 1012 | * MediaWiki:Conversiontable* is updated. |
1001 | 1013 | * @private |
1002 | 1014 | * |
1003 | | - * @param $article Object: Article object |
| 1015 | + * @param $article Article object |
1004 | 1016 | * @param $user Object: User object for the current user |
1005 | 1017 | * @param $text String: article text (?) |
1006 | 1018 | * @param $summary String: edit summary of the edit |
1007 | 1019 | * @param $isMinor Boolean: was the edit marked as minor? |
1008 | 1020 | * @param $isWatch Boolean: did the user watch this page or not? |
1009 | | - * @param $section Unused |
1010 | | - * @param $flags Bitfield |
| 1021 | + * @param $section |
| 1022 | + * @param $flags int Bitfield |
1011 | 1023 | * @param $revision Object: new Revision object or null |
1012 | 1024 | * @return Boolean: true |
1013 | 1025 | */ |
— | — | @@ -1233,6 +1245,8 @@ |
1234 | 1246 | |
1235 | 1247 | /** |
1236 | 1248 | * @private |
| 1249 | + * |
| 1250 | + * @return string |
1237 | 1251 | */ |
1238 | 1252 | function getRulesDesc() { |
1239 | 1253 | $codesep = $this->mConverter->mDescCodeSep; |
— | — | @@ -1253,6 +1267,10 @@ |
1254 | 1268 | /** |
1255 | 1269 | * Parse rules conversion. |
1256 | 1270 | * @private |
| 1271 | + * |
| 1272 | + * @param $variant |
| 1273 | + * |
| 1274 | + * @return string |
1257 | 1275 | */ |
1258 | 1276 | function getRuleConvertedStr( $variant ) { |
1259 | 1277 | $bidtable = $this->mBidtable; |
— | — | @@ -1366,19 +1384,21 @@ |
1367 | 1385 | if ( isset( $this->mVariantFlags[$variant] ) ) { |
1368 | 1386 | // then convert <text to convert> to current language |
1369 | 1387 | $this->mRules = $this->mConverter->autoConvert( $this->mRules, |
1370 | | - $variant ); |
| 1388 | + $variant ); |
1371 | 1389 | } else { // if current variant no in flags, |
1372 | 1390 | // then we check its fallback variants. |
1373 | 1391 | $variantFallbacks = |
1374 | 1392 | $this->mConverter->getVariantFallbacks( $variant ); |
1375 | | - foreach ( $variantFallbacks as $variantFallback ) { |
1376 | | - // if current variant's fallback exist in flags |
1377 | | - if ( isset( $this->mVariantFlags[$variantFallback] ) ) { |
1378 | | - // then convert <text to convert> to fallback language |
1379 | | - $this->mRules = |
1380 | | - $this->mConverter->autoConvert( $this->mRules, |
1381 | | - $variantFallback ); |
1382 | | - break; |
| 1393 | + if( is_array( $variantFallbacks ) ) { |
| 1394 | + foreach ( $variantFallbacks as $variantFallback ) { |
| 1395 | + // if current variant's fallback exist in flags |
| 1396 | + if ( isset( $this->mVariantFlags[$variantFallback] ) ) { |
| 1397 | + // then convert <text to convert> to fallback language |
| 1398 | + $this->mRules = |
| 1399 | + $this->mConverter->autoConvert( $this->mRules, |
| 1400 | + $variantFallback ); |
| 1401 | + break; |
| 1402 | + } |
1383 | 1403 | } |
1384 | 1404 | } |
1385 | 1405 | } |
— | — | @@ -1462,6 +1482,7 @@ |
1463 | 1483 | |
1464 | 1484 | /** |
1465 | 1485 | * Get display text on markup -{...}- |
| 1486 | + * @return string |
1466 | 1487 | */ |
1467 | 1488 | public function getDisplay() { |
1468 | 1489 | return $this->mRuleDisplay; |
— | — | @@ -1469,6 +1490,7 @@ |
1470 | 1491 | |
1471 | 1492 | /** |
1472 | 1493 | * Get converted title. |
| 1494 | + * @return string |
1473 | 1495 | */ |
1474 | 1496 | public function getTitle() { |
1475 | 1497 | return $this->mRuleTitle; |
— | — | @@ -1476,6 +1498,7 @@ |
1477 | 1499 | |
1478 | 1500 | /** |
1479 | 1501 | * Return how deal with conversion rules. |
| 1502 | + * @return string |
1480 | 1503 | */ |
1481 | 1504 | public function getRulesAction() { |
1482 | 1505 | return $this->mRulesAction; |
— | — | @@ -1484,6 +1507,7 @@ |
1485 | 1508 | /** |
1486 | 1509 | * Get conversion table. (bidirectional and unidirectional |
1487 | 1510 | * conversion table) |
| 1511 | + * @return array |
1488 | 1512 | */ |
1489 | 1513 | public function getConvTable() { |
1490 | 1514 | return $this->mConvTable; |
— | — | @@ -1491,6 +1515,7 @@ |
1492 | 1516 | |
1493 | 1517 | /** |
1494 | 1518 | * Get conversion rules string. |
| 1519 | + * @return string |
1495 | 1520 | */ |
1496 | 1521 | public function getRules() { |
1497 | 1522 | return $this->mRules; |
— | — | @@ -1498,6 +1523,7 @@ |
1499 | 1524 | |
1500 | 1525 | /** |
1501 | 1526 | * Get conversion flags. |
| 1527 | + * @return array |
1502 | 1528 | */ |
1503 | 1529 | public function getFlags() { |
1504 | 1530 | return $this->mFlags; |
Index: branches/nikola/phase3/tests/phpunit/languages/LanguageSrTest.php |
— | — | @@ -12,7 +12,7 @@ |
13 | 13 | * @file |
14 | 14 | */ |
15 | 15 | |
16 | | -require_once dirname(dirname(__FILE__)). '/bootstrap.php'; |
| 16 | +require_once dirname( dirname( __FILE__ ) ) . '/bootstrap.php'; |
17 | 17 | |
18 | 18 | /** Tests for MediaWiki languages/LanguageTr.php */ |
19 | 19 | class LanguageSrTest extends MediaWikiTestCase { |
— | — | @@ -20,7 +20,7 @@ |
21 | 21 | private $lang; |
22 | 22 | |
23 | 23 | function setUp() { |
24 | | - $this->lang = Language::factory( 'Sr' ); |
| 24 | + $this->lang = Language::factory( 'sr' ); |
25 | 25 | } |
26 | 26 | function tearDown() { |
27 | 27 | unset( $this->lang ); |
— | — | @@ -62,7 +62,7 @@ |
63 | 63 | } |
64 | 64 | |
65 | 65 | /** |
66 | | - * @author Nikola Smolenski |
| 66 | + * @author Nikola Smolenski |
67 | 67 | */ |
68 | 68 | function testConversionToCyrillic() { |
69 | 69 | $this->assertEquals( 'абвг', |
— | — | @@ -77,7 +77,7 @@ |
78 | 78 | $this->assertEquals( 'абвгшђжчћ', |
79 | 79 | $this->convertToCyrillic( 'абвгšđžčć' ) |
80 | 80 | ); |
81 | | - //Roman numerals are not converted |
| 81 | + // Roman numerals are not converted |
82 | 82 | $this->assertEquals( 'а I б II в III г IV шђжчћ', |
83 | 83 | $this->convertToCyrillic( 'a I b II v III g IV šđžčć' ) |
84 | 84 | ); |
— | — | @@ -96,9 +96,43 @@ |
97 | 97 | $this->assertEquals( 'абцдšđžčć', |
98 | 98 | $this->convertToLatin( 'абцдšđžčć' ) |
99 | 99 | ); |
| 100 | + } |
100 | 101 | |
| 102 | + /** @dataProvider providePluralFourForms */ |
| 103 | + function testPluralFourForms( $result, $value ) { |
| 104 | + $forms = array( 'one', 'few', 'many', 'other' ); |
| 105 | + $this->assertEquals( $result, $this->lang->convertPlural( $value, $forms ) ); |
101 | 106 | } |
102 | 107 | |
| 108 | + function providePluralFourForms() { |
| 109 | + return array ( |
| 110 | + array( 'one', 1 ), |
| 111 | + array( 'many', 11 ), |
| 112 | + array( 'one', 91 ), |
| 113 | + array( 'one', 121 ), |
| 114 | + array( 'few', 2 ), |
| 115 | + array( 'few', 3 ), |
| 116 | + array( 'few', 4 ), |
| 117 | + array( 'few', 334 ), |
| 118 | + array( 'many', 5 ), |
| 119 | + array( 'many', 15 ), |
| 120 | + array( 'many', 120 ), |
| 121 | + ); |
| 122 | + } |
| 123 | + /** @dataProvider providePluralTwoForms */ |
| 124 | + function testPluralTwoForms( $result, $value ) { |
| 125 | + $forms = array( 'one', 'several' ); |
| 126 | + $this->assertEquals( $result, $this->lang->convertPlural( $value, $forms ) ); |
| 127 | + } |
| 128 | + function providePluralTwoForms() { |
| 129 | + return array ( |
| 130 | + array( 'one', 1 ), |
| 131 | + array( 'several', 11 ), |
| 132 | + array( 'several', 91 ), |
| 133 | + array( 'several', 121 ), |
| 134 | + ); |
| 135 | + } |
| 136 | + |
103 | 137 | ##### HELPERS ##################################################### |
104 | 138 | /** |
105 | 139 | *Wrapper to verify text stay the same after applying conversion |