MediaWiki
REL1_22
|
00001 <?php 00002 00003 class LanguageTest extends LanguageClassesTestCase { 00008 public function testLanguageConvertDoubleWidthToSingleWidth() { 00009 $this->assertEquals( 00010 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 00011 $this->getLang()->normalizeForSearch( 00012 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 00013 ), 00014 'convertDoubleWidth() with the full alphabet and digits' 00015 ); 00016 } 00017 00022 public function testFormatTimePeriod( $seconds, $format, $expected, $desc ) { 00023 $this->assertEquals( $expected, $this->getLang()->formatTimePeriod( $seconds, $format ), $desc ); 00024 } 00025 00026 public static function provideFormattableTimes() { 00027 return array( 00028 array( 00029 9.45, 00030 array(), 00031 '9.5 s', 00032 'formatTimePeriod() rounding (<10s)' 00033 ), 00034 array( 00035 9.45, 00036 array( 'noabbrevs' => true ), 00037 '9.5 seconds', 00038 'formatTimePeriod() rounding (<10s)' 00039 ), 00040 array( 00041 9.95, 00042 array(), 00043 '10 s', 00044 'formatTimePeriod() rounding (<10s)' 00045 ), 00046 array( 00047 9.95, 00048 array( 'noabbrevs' => true ), 00049 '10 seconds', 00050 'formatTimePeriod() rounding (<10s)' 00051 ), 00052 array( 00053 59.55, 00054 array(), 00055 '1 min 0 s', 00056 'formatTimePeriod() rounding (<60s)' 00057 ), 00058 array( 00059 59.55, 00060 array( 'noabbrevs' => true ), 00061 '1 minute 0 seconds', 00062 'formatTimePeriod() rounding (<60s)' 00063 ), 00064 array( 00065 119.55, 00066 array(), 00067 '2 min 0 s', 00068 'formatTimePeriod() rounding (<1h)' 00069 ), 00070 array( 00071 119.55, 00072 array( 'noabbrevs' => true ), 00073 '2 minutes 0 seconds', 00074 'formatTimePeriod() rounding (<1h)' 00075 ), 00076 array( 00077 3599.55, 00078 array(), 00079 '1 h 0 min 0 s', 00080 'formatTimePeriod() rounding (<1h)' 00081 ), 00082 array( 00083 3599.55, 00084 array( 'noabbrevs' => true ), 00085 '1 hour 0 minutes 0 seconds', 00086 'formatTimePeriod() rounding (<1h)' 00087 ), 00088 array( 00089 7199.55, 00090 array(), 00091 '2 h 0 min 0 s', 00092 'formatTimePeriod() rounding (>=1h)' 00093 ), 00094 array( 00095 7199.55, 00096 array( 'noabbrevs' => true ), 00097 '2 hours 0 minutes 0 seconds', 00098 'formatTimePeriod() rounding (>=1h)' 00099 ), 00100 array( 00101 7199.55, 00102 'avoidseconds', 00103 '2 h 0 min', 00104 'formatTimePeriod() rounding (>=1h), avoidseconds' 00105 ), 00106 array( 00107 7199.55, 00108 array( 'avoid' => 'avoidseconds', 'noabbrevs' => true ), 00109 '2 hours 0 minutes', 00110 'formatTimePeriod() rounding (>=1h), avoidseconds' 00111 ), 00112 array( 00113 7199.55, 00114 'avoidminutes', 00115 '2 h 0 min', 00116 'formatTimePeriod() rounding (>=1h), avoidminutes' 00117 ), 00118 array( 00119 7199.55, 00120 array( 'avoid' => 'avoidminutes', 'noabbrevs' => true ), 00121 '2 hours 0 minutes', 00122 'formatTimePeriod() rounding (>=1h), avoidminutes' 00123 ), 00124 array( 00125 172799.55, 00126 'avoidseconds', 00127 '48 h 0 min', 00128 'formatTimePeriod() rounding (=48h), avoidseconds' 00129 ), 00130 array( 00131 172799.55, 00132 array( 'avoid' => 'avoidseconds', 'noabbrevs' => true ), 00133 '48 hours 0 minutes', 00134 'formatTimePeriod() rounding (=48h), avoidseconds' 00135 ), 00136 array( 00137 259199.55, 00138 'avoidminutes', 00139 '3 d 0 h', 00140 'formatTimePeriod() rounding (>48h), avoidminutes' 00141 ), 00142 array( 00143 259199.55, 00144 array( 'avoid' => 'avoidminutes', 'noabbrevs' => true ), 00145 '3 days 0 hours', 00146 'formatTimePeriod() rounding (>48h), avoidminutes' 00147 ), 00148 array( 00149 176399.55, 00150 'avoidseconds', 00151 '2 d 1 h 0 min', 00152 'formatTimePeriod() rounding (>48h), avoidseconds' 00153 ), 00154 array( 00155 176399.55, 00156 array( 'avoid' => 'avoidseconds', 'noabbrevs' => true ), 00157 '2 days 1 hour 0 minutes', 00158 'formatTimePeriod() rounding (>48h), avoidseconds' 00159 ), 00160 array( 00161 176399.55, 00162 'avoidminutes', 00163 '2 d 1 h', 00164 'formatTimePeriod() rounding (>48h), avoidminutes' 00165 ), 00166 array( 00167 176399.55, 00168 array( 'avoid' => 'avoidminutes', 'noabbrevs' => true ), 00169 '2 days 1 hour', 00170 'formatTimePeriod() rounding (>48h), avoidminutes' 00171 ), 00172 array( 00173 259199.55, 00174 'avoidseconds', 00175 '3 d 0 h 0 min', 00176 'formatTimePeriod() rounding (>48h), avoidseconds' 00177 ), 00178 array( 00179 259199.55, 00180 array( 'avoid' => 'avoidseconds', 'noabbrevs' => true ), 00181 '3 days 0 hours 0 minutes', 00182 'formatTimePeriod() rounding (>48h), avoidseconds' 00183 ), 00184 array( 00185 172801.55, 00186 'avoidseconds', 00187 '2 d 0 h 0 min', 00188 'formatTimePeriod() rounding, (>48h), avoidseconds' 00189 ), 00190 array( 00191 172801.55, 00192 array( 'avoid' => 'avoidseconds', 'noabbrevs' => true ), 00193 '2 days 0 hours 0 minutes', 00194 'formatTimePeriod() rounding, (>48h), avoidseconds' 00195 ), 00196 array( 00197 176460.55, 00198 array(), 00199 '2 d 1 h 1 min 1 s', 00200 'formatTimePeriod() rounding, recursion, (>48h)' 00201 ), 00202 array( 00203 176460.55, 00204 array( 'noabbrevs' => true ), 00205 '2 days 1 hour 1 minute 1 second', 00206 'formatTimePeriod() rounding, recursion, (>48h)' 00207 ), 00208 ); 00209 } 00210 00214 public function testTruncate() { 00215 $this->assertEquals( 00216 "XXX", 00217 $this->getLang()->truncate( "1234567890", 0, 'XXX' ), 00218 'truncate prefix, len 0, small ellipsis' 00219 ); 00220 00221 $this->assertEquals( 00222 "12345XXX", 00223 $this->getLang()->truncate( "1234567890", 8, 'XXX' ), 00224 'truncate prefix, small ellipsis' 00225 ); 00226 00227 $this->assertEquals( 00228 "123456789", 00229 $this->getLang()->truncate( "123456789", 5, 'XXXXXXXXXXXXXXX' ), 00230 'truncate prefix, large ellipsis' 00231 ); 00232 00233 $this->assertEquals( 00234 "XXX67890", 00235 $this->getLang()->truncate( "1234567890", -8, 'XXX' ), 00236 'truncate suffix, small ellipsis' 00237 ); 00238 00239 $this->assertEquals( 00240 "123456789", 00241 $this->getLang()->truncate( "123456789", -5, 'XXXXXXXXXXXXXXX' ), 00242 'truncate suffix, large ellipsis' 00243 ); 00244 } 00245 00250 public function testTruncateHtml( $len, $ellipsis, $input, $expected ) { 00251 // Actual HTML... 00252 $this->assertEquals( 00253 $expected, 00254 $this->getLang()->truncateHTML( $input, $len, $ellipsis ) 00255 ); 00256 } 00257 00261 public static function provideHTMLTruncateData() { 00262 return array( 00263 array( 0, 'XXX', "1234567890", "XXX" ), 00264 array( 8, 'XXX', "1234567890", "12345XXX" ), 00265 array( 5, 'XXXXXXXXXXXXXXX', '1234567890', "1234567890" ), 00266 array( 2, '***', 00267 '<p><span style="font-weight:bold;"></span></p>', 00268 '<p><span style="font-weight:bold;"></span></p>', 00269 ), 00270 array( 2, '***', 00271 '<p><span style="font-weight:bold;">123456789</span></p>', 00272 '<p><span style="font-weight:bold;">***</span></p>', 00273 ), 00274 array( 2, '***', 00275 '<p><span style="font-weight:bold;"> 23456789</span></p>', 00276 '<p><span style="font-weight:bold;">***</span></p>', 00277 ), 00278 array( 3, '***', 00279 '<p><span style="font-weight:bold;">123456789</span></p>', 00280 '<p><span style="font-weight:bold;">***</span></p>', 00281 ), 00282 array( 4, '***', 00283 '<p><span style="font-weight:bold;">123456789</span></p>', 00284 '<p><span style="font-weight:bold;">1***</span></p>', 00285 ), 00286 array( 5, '***', 00287 '<tt><span style="font-weight:bold;">123456789</span></tt>', 00288 '<tt><span style="font-weight:bold;">12***</span></tt>', 00289 ), 00290 array( 6, '***', 00291 '<p><a href="www.mediawiki.org">123456789</a></p>', 00292 '<p><a href="www.mediawiki.org">123***</a></p>', 00293 ), 00294 array( 6, '***', 00295 '<p><a href="www.mediawiki.org">12 456789</a></p>', 00296 '<p><a href="www.mediawiki.org">12 ***</a></p>', 00297 ), 00298 array( 7, '***', 00299 '<small><span style="font-weight:bold;">123<p id="#moo">456</p>789</span></small>', 00300 '<small><span style="font-weight:bold;">123<p id="#moo">4***</p></span></small>', 00301 ), 00302 array( 8, '***', 00303 '<div><span style="font-weight:bold;">123<span>4</span>56789</span></div>', 00304 '<div><span style="font-weight:bold;">123<span>4</span>5***</span></div>', 00305 ), 00306 array( 9, '***', 00307 '<p><table style="font-weight:bold;"><tr><td>123456789</td></tr></table></p>', 00308 '<p><table style="font-weight:bold;"><tr><td>123456789</td></tr></table></p>', 00309 ), 00310 array( 10, '***', 00311 '<p><font style="font-weight:bold;">123456789</font></p>', 00312 '<p><font style="font-weight:bold;">123456789</font></p>', 00313 ), 00314 ); 00315 } 00316 00322 public function testWellFormedLanguageTag( $code, $message = '' ) { 00323 $this->assertTrue( 00324 Language::isWellFormedLanguageTag( $code ), 00325 "validating code $code $message" 00326 ); 00327 } 00328 00335 public static function provideWellFormedLanguageTags() { 00336 return array( 00337 array( 'fr', 'two-letter code' ), 00338 array( 'fr-latn', 'two-letter code with lower case script code' ), 00339 array( 'fr-Latn-FR', 'two-letter code with title case script code and uppercase country code' ), 00340 array( 'fr-Latn-419', 'two-letter code with title case script code and region number' ), 00341 array( 'fr-FR', 'two-letter code with uppercase' ), 00342 array( 'ax-TZ', 'Not in the registry, but well-formed' ), 00343 array( 'fr-shadok', 'two-letter code with variant' ), 00344 array( 'fr-y-myext-myext2', 'non-x singleton' ), 00345 array( 'fra-Latn', 'ISO 639 can be 3-letters' ), 00346 array( 'fra', 'three-letter language code' ), 00347 array( 'fra-FX', 'three-letter language code with country code' ), 00348 array( 'i-klingon', 'grandfathered with singleton' ), 00349 array( 'I-kLINgon', 'tags are case-insensitive...' ), 00350 array( 'no-bok', 'grandfathered without singleton' ), 00351 array( 'i-enochian', 'Grandfathered' ), 00352 array( 'x-fr-CH', 'private use' ), 00353 array( 'es-419', 'two-letter code with region number' ), 00354 array( 'en-Latn-GB-boont-r-extended-sequence-x-private', 'weird, but well-formed' ), 00355 array( 'ab-x-abc-x-abc', 'anything goes after x' ), 00356 array( 'ab-x-abc-a-a', 'anything goes after x, including several non-x singletons' ), 00357 array( 'i-default', 'grandfathered' ), 00358 array( 'abcd-Latn', 'Language of 4 chars reserved for future use' ), 00359 array( 'AaBbCcDd-x-y-any-x', 'Language of 5-8 chars, registered' ), 00360 array( 'de-CH-1901', 'with country and year' ), 00361 array( 'en-US-x-twain', 'with country and singleton' ), 00362 array( 'zh-cmn', 'three-letter variant' ), 00363 array( 'zh-cmn-Hant', 'three-letter variant and script' ), 00364 array( 'zh-cmn-Hant-HK', 'three-letter variant, script and country' ), 00365 array( 'xr-p-lze', 'Extension' ), 00366 ); 00367 } 00368 00374 public function testMalformedLanguageTag( $code, $message = '' ) { 00375 $this->assertFalse( 00376 Language::isWellFormedLanguageTag( $code ), 00377 "validating that code $code is a malformed language tag - $message" 00378 ); 00379 } 00380 00387 public static function provideMalformedLanguageTags() { 00388 return array( 00389 array( 'f', 'language too short' ), 00390 array( 'f-Latn', 'language too short with script' ), 00391 array( 'xr-lxs-qut', 'variants too short' ), # extlangS 00392 array( 'fr-Latn-F', 'region too short' ), 00393 array( 'a-value', 'language too short with region' ), 00394 array( 'tlh-a-b-foo', 'valid three-letter with wrong variant' ), 00395 array( 'i-notexist', 'grandfathered but not registered: invalid, even if we only test well-formedness' ), 00396 array( 'abcdefghi-012345678', 'numbers too long' ), 00397 array( 'ab-abc-abc-abc-abc', 'invalid extensions' ), 00398 array( 'ab-abcd-abc', 'invalid extensions' ), 00399 array( 'ab-ab-abc', 'invalid extensions' ), 00400 array( 'ab-123-abc', 'invalid extensions' ), 00401 array( 'a-Hant-ZH', 'short language with valid extensions' ), 00402 array( 'a1-Hant-ZH', 'invalid character in language' ), 00403 array( 'ab-abcde-abc', 'invalid extensions' ), 00404 array( 'ab-1abc-abc', 'invalid characters in extensions' ), 00405 array( 'ab-ab-abcd', 'invalid order of extensions' ), 00406 array( 'ab-123-abcd', 'invalid order of extensions' ), 00407 array( 'ab-abcde-abcd', 'invalid extensions' ), 00408 array( 'ab-1abc-abcd', 'invalid characters in extensions' ), 00409 array( 'ab-a-b', 'extensions too short' ), 00410 array( 'ab-a-x', 'extensions too short, even with singleton' ), 00411 array( 'ab--ab', 'two separators' ), 00412 array( 'ab-abc-', 'separator in the end' ), 00413 array( '-ab-abc', 'separator in the beginning' ), 00414 array( 'abcd-efg', 'language too long' ), 00415 array( 'aabbccddE', 'tag too long' ), 00416 array( 'pa_guru', 'A tag with underscore is invalid in strict mode' ), 00417 array( 'de-f', 'subtag too short' ), 00418 ); 00419 } 00420 00425 public function testLenientLanguageTag() { 00426 $this->assertTrue( 00427 Language::isWellFormedLanguageTag( 'pa_guru', true ), 00428 'pa_guru is a well-formed language tag in lenient mode' 00429 ); 00430 } 00431 00437 public function testBuiltInCodeValidation( $code, $message = '' ) { 00438 $this->assertTrue( 00439 (bool)Language::isValidBuiltInCode( $code ), 00440 "validating code $code $message" 00441 ); 00442 } 00443 00447 public function testBuiltInCodeValidationRejectUnderscore() { 00448 $this->assertFalse( 00449 (bool)Language::isValidBuiltInCode( 'be_tarask' ), 00450 "reject underscore in language code" 00451 ); 00452 } 00453 00454 public static function provideLanguageCodes() { 00455 return array( 00456 array( 'fr', 'Two letters, minor case' ), 00457 array( 'EN', 'Two letters, upper case' ), 00458 array( 'tyv', 'Three letters' ), 00459 array( 'tokipona', 'long language code' ), 00460 array( 'be-tarask', 'With dash' ), 00461 array( 'Zh-classical', 'Begin with upper case, dash' ), 00462 array( 'Be-x-old', 'With extension (two dashes)' ), 00463 ); 00464 } 00465 00471 public function testKnownLanguageTag( $code, $message = '' ) { 00472 $this->assertTrue( 00473 (bool)Language::isKnownLanguageTag( $code ), 00474 "validating code $code - $message" 00475 ); 00476 } 00477 00478 public static function provideKnownLanguageTags() { 00479 return array( 00480 array( 'fr', 'simple code' ), 00481 array( 'bat-smg', 'an MW legacy tag' ), 00482 array( 'sgs', 'an internal standard MW name, for which a legacy tag is used externally' ), 00483 ); 00484 } 00485 00489 public function testKnownCldrLanguageTag() { 00490 if ( !class_exists( 'LanguageNames' ) ) { 00491 $this->markTestSkipped( 'The LanguageNames class is not available. The cldr extension is probably not installed.' ); 00492 } 00493 00494 $this->assertTrue( 00495 (bool)Language::isKnownLanguageTag( 'pal' ), 00496 'validating code "pal" an ancient language, which probably will not appear in Names.php, but appears in CLDR in English' 00497 ); 00498 } 00499 00505 public function testUnknownLanguageTag( $code, $message = '' ) { 00506 $this->assertFalse( 00507 (bool)Language::isKnownLanguageTag( $code ), 00508 "checking that code $code is invalid - $message" 00509 ); 00510 } 00511 00512 public static function provideUnknownLanguageTags() { 00513 return array( 00514 array( 'mw', 'non-existent two-letter code' ), 00515 array( 'foo"<bar', 'very invalid language code' ), 00516 ); 00517 } 00518 00524 public function testSprintfDateTooShortTimestamp() { 00525 $this->getLang()->sprintfDate( 'xiY', '1234567890123' ); 00526 } 00527 00533 public function testSprintfDateTooLongTimestamp() { 00534 $this->getLang()->sprintfDate( 'xiY', '123456789012345' ); 00535 } 00536 00542 public function testSprintfDateNotAllDigitTimestamp() { 00543 $this->getLang()->sprintfDate( 'xiY', '-1234567890123' ); 00544 } 00545 00550 public function testSprintfDate( $format, $ts, $expected, $msg ) { 00551 $this->assertEquals( 00552 $expected, 00553 $this->getLang()->sprintfDate( $format, $ts ), 00554 "sprintfDate('$format', '$ts'): $msg" 00555 ); 00556 } 00557 00563 public function testSprintfDateNoZone( $format, $ts, $expected, $ignore, $msg ) { 00564 $oldTZ = date_default_timezone_get(); 00565 $res = date_default_timezone_set( 'Asia/Seoul' ); 00566 if ( !$res ) { 00567 $this->markTestSkipped( "Error setting Timezone" ); 00568 } 00569 00570 $this->assertEquals( 00571 $expected, 00572 $this->getLang()->sprintfDate( $format, $ts ), 00573 "sprintfDate('$format', '$ts'): $msg" 00574 ); 00575 00576 date_default_timezone_set( $oldTZ ); 00577 } 00578 00584 public function testSprintfDateTZ( $format, $ts, $ignore, $expected, $msg ) { 00585 $tz = new DateTimeZone( 'Asia/Seoul' ); 00586 if ( !$tz ) { 00587 $this->markTestSkipped( "Error getting Timezone" ); 00588 } 00589 00590 $this->assertEquals( 00591 $expected, 00592 $this->getLang()->sprintfDate( $format, $ts, $tz ), 00593 "sprintfDate('$format', '$ts', 'Asia/Seoul'): $msg" 00594 ); 00595 } 00596 00597 public static function provideSprintfDateSamples() { 00598 return array( 00599 array( 00600 'xiY', 00601 '20111212000000', 00602 '1390', // note because we're testing English locale we get Latin-standard digits 00603 '1390', 00604 'Iranian calendar full year' 00605 ), 00606 array( 00607 'xiy', 00608 '20111212000000', 00609 '90', 00610 '90', 00611 'Iranian calendar short year' 00612 ), 00613 array( 00614 'o', 00615 '20120101235000', 00616 '2011', 00617 '2011', 00618 'ISO 8601 (week) year' 00619 ), 00620 array( 00621 'W', 00622 '20120101235000', 00623 '52', 00624 '52', 00625 'Week number' 00626 ), 00627 array( 00628 'W', 00629 '20120102235000', 00630 '1', 00631 '1', 00632 'Week number' 00633 ), 00634 array( 00635 'o-\\WW-N', 00636 '20091231235000', 00637 '2009-W53-4', 00638 '2009-W53-4', 00639 'leap week' 00640 ), 00641 // What follows is mostly copied from http://www.mediawiki.org/wiki/Help:Extension:ParserFunctions#.23time 00642 array( 00643 'Y', 00644 '20120102090705', 00645 '2012', 00646 '2012', 00647 'Full year' 00648 ), 00649 array( 00650 'y', 00651 '20120102090705', 00652 '12', 00653 '12', 00654 '2 digit year' 00655 ), 00656 array( 00657 'L', 00658 '20120102090705', 00659 '1', 00660 '1', 00661 'Leap year' 00662 ), 00663 array( 00664 'n', 00665 '20120102090705', 00666 '1', 00667 '1', 00668 'Month index, not zero pad' 00669 ), 00670 array( 00671 'N', 00672 '20120102090705', 00673 '01', 00674 '01', 00675 'Month index. Zero pad' 00676 ), 00677 array( 00678 'M', 00679 '20120102090705', 00680 'Jan', 00681 'Jan', 00682 'Month abbrev' 00683 ), 00684 array( 00685 'F', 00686 '20120102090705', 00687 'January', 00688 'January', 00689 'Full month' 00690 ), 00691 array( 00692 'xg', 00693 '20120102090705', 00694 'January', 00695 'January', 00696 'Genitive month name (same in EN)' 00697 ), 00698 array( 00699 'j', 00700 '20120102090705', 00701 '2', 00702 '2', 00703 'Day of month (not zero pad)' 00704 ), 00705 array( 00706 'd', 00707 '20120102090705', 00708 '02', 00709 '02', 00710 'Day of month (zero-pad)' 00711 ), 00712 array( 00713 'z', 00714 '20120102090705', 00715 '1', 00716 '1', 00717 'Day of year (zero-indexed)' 00718 ), 00719 array( 00720 'D', 00721 '20120102090705', 00722 'Mon', 00723 'Mon', 00724 'Day of week (abbrev)' 00725 ), 00726 array( 00727 'l', 00728 '20120102090705', 00729 'Monday', 00730 'Monday', 00731 'Full day of week' 00732 ), 00733 array( 00734 'N', 00735 '20120101090705', 00736 '7', 00737 '7', 00738 'Day of week (Mon=1, Sun=7)' 00739 ), 00740 array( 00741 'w', 00742 '20120101090705', 00743 '0', 00744 '0', 00745 'Day of week (Sun=0, Sat=6)' 00746 ), 00747 array( 00748 'N', 00749 '20120102090705', 00750 '1', 00751 '1', 00752 'Day of week' 00753 ), 00754 array( 00755 'a', 00756 '20120102090705', 00757 'am', 00758 'am', 00759 'am vs pm' 00760 ), 00761 array( 00762 'A', 00763 '20120102120000', 00764 'PM', 00765 'PM', 00766 'AM vs PM' 00767 ), 00768 array( 00769 'a', 00770 '20120102000000', 00771 'am', 00772 'am', 00773 'AM vs PM' 00774 ), 00775 array( 00776 'g', 00777 '20120102090705', 00778 '9', 00779 '9', 00780 '12 hour, not Zero' 00781 ), 00782 array( 00783 'h', 00784 '20120102090705', 00785 '09', 00786 '09', 00787 '12 hour, zero padded' 00788 ), 00789 array( 00790 'G', 00791 '20120102090705', 00792 '9', 00793 '9', 00794 '24 hour, not zero' 00795 ), 00796 array( 00797 'H', 00798 '20120102090705', 00799 '09', 00800 '09', 00801 '24 hour, zero' 00802 ), 00803 array( 00804 'H', 00805 '20120102110705', 00806 '11', 00807 '11', 00808 '24 hour, zero' 00809 ), 00810 array( 00811 'i', 00812 '20120102090705', 00813 '07', 00814 '07', 00815 'Minutes' 00816 ), 00817 array( 00818 's', 00819 '20120102090705', 00820 '05', 00821 '05', 00822 'seconds' 00823 ), 00824 array( 00825 'U', 00826 '20120102090705', 00827 '1325495225', 00828 '1325462825', 00829 'unix time' 00830 ), 00831 array( 00832 't', 00833 '20120102090705', 00834 '31', 00835 '31', 00836 'Days in current month' 00837 ), 00838 array( 00839 'c', 00840 '20120102090705', 00841 '2012-01-02T09:07:05+00:00', 00842 '2012-01-02T09:07:05+09:00', 00843 'ISO 8601 timestamp' 00844 ), 00845 array( 00846 'r', 00847 '20120102090705', 00848 'Mon, 02 Jan 2012 09:07:05 +0000', 00849 'Mon, 02 Jan 2012 09:07:05 +0900', 00850 'RFC 5322' 00851 ), 00852 array( 00853 'e', 00854 '20120102090705', 00855 'UTC', 00856 'Asia/Seoul', 00857 'Timezone identifier' 00858 ), 00859 array( 00860 'I', 00861 '19880602090705', 00862 '0', 00863 '1', 00864 'DST indicator' 00865 ), 00866 array( 00867 'O', 00868 '20120102090705', 00869 '+0000', 00870 '+0900', 00871 'Timezone offset' 00872 ), 00873 array( 00874 'P', 00875 '20120102090705', 00876 '+00:00', 00877 '+09:00', 00878 'Timezone offset with colon' 00879 ), 00880 array( 00881 'T', 00882 '20120102090705', 00883 'UTC', 00884 'KST', 00885 'Timezone abbreviation' 00886 ), 00887 array( 00888 'Z', 00889 '20120102090705', 00890 '0', 00891 '32400', 00892 'Timezone offset in seconds' 00893 ), 00894 array( 00895 'xmj xmF xmn xmY', 00896 '20120102090705', 00897 '7 Safar 2 1433', 00898 '7 Safar 2 1433', 00899 'Islamic' 00900 ), 00901 array( 00902 'xij xiF xin xiY', 00903 '20120102090705', 00904 '12 Dey 10 1390', 00905 '12 Dey 10 1390', 00906 'Iranian' 00907 ), 00908 array( 00909 'xjj xjF xjn xjY', 00910 '20120102090705', 00911 '7 Tevet 4 5772', 00912 '7 Tevet 4 5772', 00913 'Hebrew' 00914 ), 00915 array( 00916 'xjt', 00917 '20120102090705', 00918 '29', 00919 '29', 00920 'Hebrew number of days in month' 00921 ), 00922 array( 00923 'xjx', 00924 '20120102090705', 00925 'Tevet', 00926 'Tevet', 00927 'Hebrew genitive month name (No difference in EN)' 00928 ), 00929 array( 00930 'xkY', 00931 '20120102090705', 00932 '2555', 00933 '2555', 00934 'Thai year' 00935 ), 00936 array( 00937 'xoY', 00938 '20120102090705', 00939 '101', 00940 '101', 00941 'Minguo' 00942 ), 00943 array( 00944 'xtY', 00945 '20120102090705', 00946 '平成24', 00947 '平成24', 00948 'nengo' 00949 ), 00950 array( 00951 'xrxkYY', 00952 '20120102090705', 00953 'MMDLV2012', 00954 'MMDLV2012', 00955 'Roman numerals' 00956 ), 00957 array( 00958 'xhxjYY', 00959 '20120102090705', 00960 'ה\'תשע"ב2012', 00961 'ה\'תשע"ב2012', 00962 'Hebrew numberals' 00963 ), 00964 array( 00965 'xnY', 00966 '20120102090705', 00967 '2012', 00968 '2012', 00969 'Raw numerals (doesn\'t mean much in EN)' 00970 ), 00971 array( 00972 '[[Y "(yea"\\r)]] \\"xx\\"', 00973 '20120102090705', 00974 '[[2012 (year)]] "x"', 00975 '[[2012 (year)]] "x"', 00976 'Various escaping' 00977 ), 00978 00979 ); 00980 } 00981 00986 public function testFormatSize( $size, $expected, $msg ) { 00987 $this->assertEquals( 00988 $expected, 00989 $this->getLang()->formatSize( $size ), 00990 "formatSize('$size'): $msg" 00991 ); 00992 } 00993 00994 public static function provideFormatSizes() { 00995 return array( 00996 array( 00997 0, 00998 "0 B", 00999 "Zero bytes" 01000 ), 01001 array( 01002 1024, 01003 "1 KB", 01004 "1 kilobyte" 01005 ), 01006 array( 01007 1024 * 1024, 01008 "1 MB", 01009 "1,024 megabytes" 01010 ), 01011 array( 01012 1024 * 1024 * 1024, 01013 "1 GB", 01014 "1 gigabytes" 01015 ), 01016 array( 01017 pow( 1024, 4 ), 01018 "1 TB", 01019 "1 terabyte" 01020 ), 01021 array( 01022 pow( 1024, 5 ), 01023 "1 PB", 01024 "1 petabyte" 01025 ), 01026 array( 01027 pow( 1024, 6 ), 01028 "1 EB", 01029 "1,024 exabyte" 01030 ), 01031 array( 01032 pow( 1024, 7 ), 01033 "1 ZB", 01034 "1 zetabyte" 01035 ), 01036 array( 01037 pow( 1024, 8 ), 01038 "1 YB", 01039 "1 yottabyte" 01040 ), 01041 // How big!? THIS BIG! 01042 ); 01043 } 01044 01049 public function testFormatBitrate( $bps, $expected, $msg ) { 01050 $this->assertEquals( 01051 $expected, 01052 $this->getLang()->formatBitrate( $bps ), 01053 "formatBitrate('$bps'): $msg" 01054 ); 01055 } 01056 01057 public static function provideFormatBitrate() { 01058 return array( 01059 array( 01060 0, 01061 "0 bps", 01062 "0 bits per second" 01063 ), 01064 array( 01065 999, 01066 "999 bps", 01067 "999 bits per second" 01068 ), 01069 array( 01070 1000, 01071 "1 kbps", 01072 "1 kilobit per second" 01073 ), 01074 array( 01075 1000 * 1000, 01076 "1 Mbps", 01077 "1 megabit per second" 01078 ), 01079 array( 01080 pow( 10, 9 ), 01081 "1 Gbps", 01082 "1 gigabit per second" 01083 ), 01084 array( 01085 pow( 10, 12 ), 01086 "1 Tbps", 01087 "1 terabit per second" 01088 ), 01089 array( 01090 pow( 10, 15 ), 01091 "1 Pbps", 01092 "1 petabit per second" 01093 ), 01094 array( 01095 pow( 10, 18 ), 01096 "1 Ebps", 01097 "1 exabit per second" 01098 ), 01099 array( 01100 pow( 10, 21 ), 01101 "1 Zbps", 01102 "1 zetabit per second" 01103 ), 01104 array( 01105 pow( 10, 24 ), 01106 "1 Ybps", 01107 "1 yottabit per second" 01108 ), 01109 array( 01110 pow( 10, 27 ), 01111 "1,000 Ybps", 01112 "1,000 yottabits per second" 01113 ), 01114 ); 01115 } 01116 01117 01122 public function testFormatDuration( $duration, $expected, $intervals = array() ) { 01123 $this->assertEquals( 01124 $expected, 01125 $this->getLang()->formatDuration( $duration, $intervals ), 01126 "formatDuration('$duration'): $expected" 01127 ); 01128 } 01129 01130 public static function provideFormatDuration() { 01131 return array( 01132 array( 01133 0, 01134 '0 seconds', 01135 ), 01136 array( 01137 1, 01138 '1 second', 01139 ), 01140 array( 01141 2, 01142 '2 seconds', 01143 ), 01144 array( 01145 60, 01146 '1 minute', 01147 ), 01148 array( 01149 2 * 60, 01150 '2 minutes', 01151 ), 01152 array( 01153 3600, 01154 '1 hour', 01155 ), 01156 array( 01157 2 * 3600, 01158 '2 hours', 01159 ), 01160 array( 01161 24 * 3600, 01162 '1 day', 01163 ), 01164 array( 01165 2 * 86400, 01166 '2 days', 01167 ), 01168 array( 01169 // ( 365 + ( 24 * 3 + 25 ) / 400 ) * 86400 = 31556952 01170 ( 365 + ( 24 * 3 + 25 ) / 400.0 ) * 86400, 01171 '1 year', 01172 ), 01173 array( 01174 2 * 31556952, 01175 '2 years', 01176 ), 01177 array( 01178 10 * 31556952, 01179 '1 decade', 01180 ), 01181 array( 01182 20 * 31556952, 01183 '2 decades', 01184 ), 01185 array( 01186 100 * 31556952, 01187 '1 century', 01188 ), 01189 array( 01190 200 * 31556952, 01191 '2 centuries', 01192 ), 01193 array( 01194 1000 * 31556952, 01195 '1 millennium', 01196 ), 01197 array( 01198 2000 * 31556952, 01199 '2 millennia', 01200 ), 01201 array( 01202 9001, 01203 '2 hours, 30 minutes and 1 second' 01204 ), 01205 array( 01206 3601, 01207 '1 hour and 1 second' 01208 ), 01209 array( 01210 31556952 + 2 * 86400 + 9000, 01211 '1 year, 2 days, 2 hours and 30 minutes' 01212 ), 01213 array( 01214 42 * 1000 * 31556952 + 42, 01215 '42 millennia and 42 seconds' 01216 ), 01217 array( 01218 60, 01219 '60 seconds', 01220 array( 'seconds' ), 01221 ), 01222 array( 01223 61, 01224 '61 seconds', 01225 array( 'seconds' ), 01226 ), 01227 array( 01228 1, 01229 '1 second', 01230 array( 'seconds' ), 01231 ), 01232 array( 01233 31556952 + 2 * 86400 + 9000, 01234 '1 year, 2 days and 150 minutes', 01235 array( 'years', 'days', 'minutes' ), 01236 ), 01237 array( 01238 42, 01239 '0 days', 01240 array( 'years', 'days' ), 01241 ), 01242 array( 01243 31556952 + 2 * 86400 + 9000, 01244 '1 year, 2 days and 150 minutes', 01245 array( 'minutes', 'days', 'years' ), 01246 ), 01247 array( 01248 42, 01249 '0 days', 01250 array( 'days', 'years' ), 01251 ), 01252 ); 01253 } 01254 01259 public function testCheckTitleEncoding( $s ) { 01260 $this->assertEquals( 01261 $s, 01262 $this->getLang()->checkTitleEncoding( $s ), 01263 "checkTitleEncoding('$s')" 01264 ); 01265 } 01266 01267 public static function provideCheckTitleEncodingData() { 01268 return array( 01269 array( "" ), 01270 array( "United States of America" ), // 7bit ASCII 01271 array( rawurldecode( "S%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e" ) ), 01272 array( 01273 rawurldecode( 01274 "Acteur%7CAlbert%20Robbins%7CAnglais%7CAnn%20Donahue%7CAnthony%20E.%20Zuiker%7CCarol%20Mendelsohn" 01275 ) 01276 ), 01277 // The following two data sets come from bug 36839. They fail if checkTitleEncoding uses a regexp to test for 01278 // valid UTF-8 encoding and the pcre.recursion_limit is low (like, say, 1024). They succeed if checkTitleEncoding 01279 // uses mb_check_encoding for its test. 01280 array( 01281 rawurldecode( 01282 "Acteur%7CAlbert%20Robbins%7CAnglais%7CAnn%20Donahue%7CAnthony%20E.%20Zuiker%7CCarol%20Mendelsohn%7C" 01283 . "Catherine%20Willows%7CDavid%20Hodges%7CDavid%20Phillips%7CGil%20Grissom%7CGreg%20Sanders%7CHodges%7C" 01284 . "Internet%20Movie%20Database%7CJim%20Brass%7CLady%20Heather%7C" 01285 . "Les%20Experts%20(s%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e)%7CLes%20Experts%20:%20Manhattan%7C" 01286 . "Les%20Experts%20:%20Miami%7CListe%20des%20personnages%20des%20Experts%7C" 01287 . "Liste%20des%20%C3%A9pisodes%20des%20Experts%7CMod%C3%A8le%20discussion:Palette%20Les%20Experts%7C" 01288 . "Nick%20Stokes%7CPersonnage%20de%20fiction%7CPersonnage%20fictif%7CPersonnage%20de%20fiction%7C" 01289 . "Personnages%20r%C3%A9currents%20dans%20Les%20Experts%7CRaymond%20Langston%7CRiley%20Adams%7C" 01290 . "Saison%201%20des%20Experts%7CSaison%2010%20des%20Experts%7CSaison%2011%20des%20Experts%7C" 01291 . "Saison%2012%20des%20Experts%7CSaison%202%20des%20Experts%7CSaison%203%20des%20Experts%7C" 01292 . "Saison%204%20des%20Experts%7CSaison%205%20des%20Experts%7CSaison%206%20des%20Experts%7C" 01293 . "Saison%207%20des%20Experts%7CSaison%208%20des%20Experts%7CSaison%209%20des%20Experts%7C" 01294 . "Sara%20Sidle%7CSofia%20Curtis%7CS%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e%7CWallace%20Langham%7C" 01295 . "Warrick%20Brown%7CWendy%20Simms%7C%C3%89tats-Unis" 01296 ), 01297 ), 01298 array( 01299 rawurldecode( 01300 "Mod%C3%A8le%3AArrondissements%20homonymes%7CMod%C3%A8le%3ABandeau%20standard%20pour%20page%20d'homonymie%7C" 01301 . "Mod%C3%A8le%3ABatailles%20homonymes%7CMod%C3%A8le%3ACantons%20homonymes%7C" 01302 . "Mod%C3%A8le%3ACommunes%20fran%C3%A7aises%20homonymes%7CMod%C3%A8le%3AFilms%20homonymes%7C" 01303 . "Mod%C3%A8le%3AGouvernements%20homonymes%7CMod%C3%A8le%3AGuerres%20homonymes%7CMod%C3%A8le%3AHomonymie%7C" 01304 . "Mod%C3%A8le%3AHomonymie%20bateau%7CMod%C3%A8le%3AHomonymie%20d'%C3%A9tablissements%20scolaires%20ou" 01305 . "%20universitaires%7CMod%C3%A8le%3AHomonymie%20d'%C3%AEles%7CMod%C3%A8le%3AHomonymie%20de%20clubs%20sportifs%7C" 01306 . "Mod%C3%A8le%3AHomonymie%20de%20comt%C3%A9s%7CMod%C3%A8le%3AHomonymie%20de%20monument%7C" 01307 . "Mod%C3%A8le%3AHomonymie%20de%20nom%20romain%7CMod%C3%A8le%3AHomonymie%20de%20parti%20politique%7C" 01308 . "Mod%C3%A8le%3AHomonymie%20de%20route%7CMod%C3%A8le%3AHomonymie%20dynastique%7C" 01309 . "Mod%C3%A8le%3AHomonymie%20vid%C3%A9oludique%7CMod%C3%A8le%3AHomonymie%20%C3%A9difice%20religieux%7C" 01310 . "Mod%C3%A8le%3AInternationalisation%7CMod%C3%A8le%3AIsom%C3%A9rie%7CMod%C3%A8le%3AParonymie%7C" 01311 . "Mod%C3%A8le%3APatronyme%7CMod%C3%A8le%3APatronyme%20basque%7CMod%C3%A8le%3APatronyme%20italien%7C" 01312 . "Mod%C3%A8le%3APatronymie%7CMod%C3%A8le%3APersonnes%20homonymes%7CMod%C3%A8le%3ASaints%20homonymes%7C" 01313 . "Mod%C3%A8le%3ATitres%20homonymes%7CMod%C3%A8le%3AToponymie%7CMod%C3%A8le%3AUnit%C3%A9s%20homonymes%7C" 01314 . "Mod%C3%A8le%3AVilles%20homonymes%7CMod%C3%A8le%3A%C3%89difices%20religieux%20homonymes" 01315 ) 01316 ) 01317 ); 01318 } 01319 01324 public function testRomanNumerals( $num, $numerals ) { 01325 $this->assertEquals( 01326 $numerals, 01327 Language::romanNumeral( $num ), 01328 "romanNumeral('$num')" 01329 ); 01330 } 01331 01332 public static function provideRomanNumeralsData() { 01333 return array( 01334 array( 1, 'I' ), 01335 array( 2, 'II' ), 01336 array( 3, 'III' ), 01337 array( 4, 'IV' ), 01338 array( 5, 'V' ), 01339 array( 6, 'VI' ), 01340 array( 7, 'VII' ), 01341 array( 8, 'VIII' ), 01342 array( 9, 'IX' ), 01343 array( 10, 'X' ), 01344 array( 20, 'XX' ), 01345 array( 30, 'XXX' ), 01346 array( 40, 'XL' ), 01347 array( 49, 'XLIX' ), 01348 array( 50, 'L' ), 01349 array( 60, 'LX' ), 01350 array( 70, 'LXX' ), 01351 array( 80, 'LXXX' ), 01352 array( 90, 'XC' ), 01353 array( 99, 'XCIX' ), 01354 array( 100, 'C' ), 01355 array( 200, 'CC' ), 01356 array( 300, 'CCC' ), 01357 array( 400, 'CD' ), 01358 array( 500, 'D' ), 01359 array( 600, 'DC' ), 01360 array( 700, 'DCC' ), 01361 array( 800, 'DCCC' ), 01362 array( 900, 'CM' ), 01363 array( 999, 'CMXCIX' ), 01364 array( 1000, 'M' ), 01365 array( 1989, 'MCMLXXXIX' ), 01366 array( 2000, 'MM' ), 01367 array( 3000, 'MMM' ), 01368 array( 4000, 'MMMM' ), 01369 array( 5000, 'MMMMM' ), 01370 array( 6000, 'MMMMMM' ), 01371 array( 7000, 'MMMMMMM' ), 01372 array( 8000, 'MMMMMMMM' ), 01373 array( 9000, 'MMMMMMMMM' ), 01374 array( 9999, 'MMMMMMMMMCMXCIX' ), 01375 array( 10000, 'MMMMMMMMMM' ), 01376 ); 01377 } 01378 01383 public function testConvertPlural( $expected, $number, $forms ) { 01384 $chosen = $this->getLang()->convertPlural( $number, $forms ); 01385 $this->assertEquals( $expected, $chosen ); 01386 } 01387 01388 public static function providePluralData() { 01389 // Params are: [expected text, number given, [the plural forms]] 01390 return array( 01391 array( 'plural', 0, array( 01392 'singular', 'plural' 01393 ) ), 01394 array( 'explicit zero', 0, array( 01395 '0=explicit zero', 'singular', 'plural' 01396 ) ), 01397 array( 'explicit one', 1, array( 01398 'singular', 'plural', '1=explicit one', 01399 ) ), 01400 array( 'singular', 1, array( 01401 'singular', 'plural', '0=explicit zero', 01402 ) ), 01403 array( 'plural', 3, array( 01404 '0=explicit zero', '1=explicit one', 'singular', 'plural' 01405 ) ), 01406 array( 'explicit eleven', 11, array( 01407 'singular', 'plural', '11=explicit eleven', 01408 ) ), 01409 array( 'plural', 12, array( 01410 'singular', 'plural', '11=explicit twelve', 01411 ) ), 01412 array( 'plural', 12, array( 01413 'singular', 'plural', '=explicit form', 01414 ) ), 01415 array( 'other', 2, array( 01416 'kissa=kala', '1=2=3', 'other', 01417 ) ), 01418 array( '', 2, array( 01419 '0=explicit zero', '1=explicit one', 01420 ) ), 01421 ); 01422 } 01423 01428 public function testTranslateBlockExpiry( $expectedData, $str, $desc ) { 01429 $lang = $this->getLang(); 01430 if ( is_array( $expectedData ) ) { 01431 list( $func, $arg ) = $expectedData; 01432 $expected = $lang->$func( $arg ); 01433 } else { 01434 $expected = $expectedData; 01435 } 01436 $this->assertEquals( $expected, $lang->translateBlockExpiry( $str ), $desc ); 01437 } 01438 01439 public static function provideTranslateBlockExpiry() { 01440 return array( 01441 array( '2 hours', '2 hours', 'simple data from ipboptions' ), 01442 array( 'indefinite', 'infinite', 'infinite from ipboptions' ), 01443 array( 'indefinite', 'infinity', 'alternative infinite from ipboptions' ), 01444 array( 'indefinite', 'indefinite', 'another alternative infinite from ipboptions' ), 01445 array( array( 'formatDuration', 1023 * 60 * 60 ), '1023 hours', 'relative' ), 01446 array( array( 'formatDuration', -1023 ), '-1023 seconds', 'negative relative' ), 01447 array( array( 'formatDuration', 0 ), 'now', 'now' ), 01448 array( array( 'timeanddate', '20120102070000' ), '2012-1-1 7:00 +1 day', 'mixed, handled as absolute' ), 01449 array( array( 'timeanddate', '19910203040506' ), '1991-2-3 4:05:06', 'absolute' ), 01450 array( array( 'timeanddate', '19700101000000' ), '1970-1-1 0:00:00', 'absolute at epoch' ), 01451 array( array( 'timeanddate', '19691231235959' ), '1969-12-31 23:59:59', 'time before epoch' ), 01452 array( 'dummy', 'dummy', 'return garbage as is' ), 01453 ); 01454 } 01455 01460 public function testCommafy( $number, $numbersWithCommas ) { 01461 $this->assertEquals( 01462 $numbersWithCommas, 01463 $this->getLang()->commafy( $number ), 01464 "commafy('$number')" 01465 ); 01466 } 01467 01468 public static function provideCommafyData() { 01469 return array( 01470 array( 1, '1' ), 01471 array( 10, '10' ), 01472 array( 100, '100' ), 01473 array( 1000, '1,000' ), 01474 array( 10000, '10,000' ), 01475 array( 100000, '100,000' ), 01476 array( 1000000, '1,000,000' ), 01477 array( 1.0001, '1.0001' ), 01478 array( 10.0001, '10.0001' ), 01479 array( 100.0001, '100.0001' ), 01480 array( 1000.0001, '1,000.0001' ), 01481 array( 10000.0001, '10,000.0001' ), 01482 array( 100000.0001, '100,000.0001' ), 01483 array( 1000000.0001, '1,000,000.0001' ), 01484 ); 01485 } 01486 01490 public function testListToText() { 01491 $lang = $this->getLang(); 01492 $and = $lang->getMessageFromDB( 'and' ); 01493 $s = $lang->getMessageFromDB( 'word-separator' ); 01494 $c = $lang->getMessageFromDB( 'comma-separator' ); 01495 01496 $this->assertEquals( '', $lang->listToText( array() ) ); 01497 $this->assertEquals( 'a', $lang->listToText( array( 'a' ) ) ); 01498 $this->assertEquals( "a{$and}{$s}b", $lang->listToText( array( 'a', 'b' ) ) ); 01499 $this->assertEquals( "a{$c}b{$and}{$s}c", $lang->listToText( array( 'a', 'b', 'c' ) ) ); 01500 $this->assertEquals( "a{$c}b{$c}c{$and}{$s}d", $lang->listToText( array( 'a', 'b', 'c', 'd' ) ) ); 01501 } 01502 01507 public function testIsSupportedLanguage( $code, $expected, $comment ) { 01508 $this->assertEquals( $expected, Language::isSupportedLanguage( $code ), $comment ); 01509 } 01510 01511 public static function provideIsSupportedLanguage() { 01512 return array( 01513 array( 'en', true, 'is supported language' ), 01514 array( 'fi', true, 'is supported language' ), 01515 array( 'bunny', false, 'is not supported language' ), 01516 array( 'FI', false, 'is not supported language, input should be in lower case' ), 01517 ); 01518 } 01519 01524 public function testGetParentLanguage( $code, $expected, $comment ) { 01525 $lang = Language::factory( $code ); 01526 if ( is_null( $expected ) ) { 01527 $this->assertNull( $lang->getParentLanguage(), $comment ); 01528 } else { 01529 $this->assertEquals( $expected, $lang->getParentLanguage()->getCode(), $comment ); 01530 } 01531 } 01532 01533 public static function provideGetParentLanguage() { 01534 return array( 01535 array( 'zh-cn', 'zh', 'zh is the parent language of zh-cn' ), 01536 array( 'zh', 'zh', 'zh is defined as the parent language of zh, because zh converter can convert zh-cn to zh' ), 01537 array( 'zh-invalid', null, 'do not be fooled by arbitrarily composed language codes' ), 01538 array( 'en-gb', null, 'en does not have converter' ), 01539 array( 'en', null, 'en does not have converter. Although FakeConverter handles en -> en conversion but it is useless' ), 01540 ); 01541 } 01542 01547 public function testGetNamespaceAliases( $languageCode, $subset ) { 01548 $language = Language::factory( $languageCode ); 01549 $aliases = $language->getNamespaceAliases(); 01550 foreach ( $subset as $alias => $nsId ) { 01551 $this->assertEquals( $nsId, $aliases[$alias] ); 01552 } 01553 } 01554 01555 public static function provideGetNamespaceAliases() { 01556 // TODO: Add tests for NS_PROJECT_TALK and GenderNamespaces 01557 return array( 01558 array( 01559 'zh', 01560 array( 01561 '文件' => NS_FILE, 01562 '檔案' => NS_FILE, 01563 ), 01564 ), 01565 ); 01566 } 01567 }