MediaWiki
REL1_24
|
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 $this->assertEquals( 00245 "123XXX", 00246 $this->getLang()->truncate( "123 ", 9, 'XXX' ), 00247 'truncate prefix, with spaces' 00248 ); 00249 $this->assertEquals( 00250 "12345XXX", 00251 $this->getLang()->truncate( "12345 8", 11, 'XXX' ), 00252 'truncate prefix, with spaces and non-space ending' 00253 ); 00254 $this->assertEquals( 00255 "XXX234", 00256 $this->getLang()->truncate( "1 234", -8, 'XXX' ), 00257 'truncate suffix, with spaces' 00258 ); 00259 $this->assertEquals( 00260 "12345XXX", 00261 $this->getLang()->truncate( "1234567890", 5, 'XXX', false ), 00262 'truncate without adjustment' 00263 ); 00264 } 00265 00270 public function testTruncateHtml( $len, $ellipsis, $input, $expected ) { 00271 // Actual HTML... 00272 $this->assertEquals( 00273 $expected, 00274 $this->getLang()->truncateHTML( $input, $len, $ellipsis ) 00275 ); 00276 } 00277 00281 public static function provideHTMLTruncateData() { 00282 return array( 00283 array( 0, 'XXX', "1234567890", "XXX" ), 00284 array( 8, 'XXX', "1234567890", "12345XXX" ), 00285 array( 5, 'XXXXXXXXXXXXXXX', '1234567890', "1234567890" ), 00286 array( 2, '***', 00287 '<p><span style="font-weight:bold;"></span></p>', 00288 '<p><span style="font-weight:bold;"></span></p>', 00289 ), 00290 array( 2, '***', 00291 '<p><span style="font-weight:bold;">123456789</span></p>', 00292 '<p><span style="font-weight:bold;">***</span></p>', 00293 ), 00294 array( 2, '***', 00295 '<p><span style="font-weight:bold;"> 23456789</span></p>', 00296 '<p><span style="font-weight:bold;">***</span></p>', 00297 ), 00298 array( 3, '***', 00299 '<p><span style="font-weight:bold;">123456789</span></p>', 00300 '<p><span style="font-weight:bold;">***</span></p>', 00301 ), 00302 array( 4, '***', 00303 '<p><span style="font-weight:bold;">123456789</span></p>', 00304 '<p><span style="font-weight:bold;">1***</span></p>', 00305 ), 00306 array( 5, '***', 00307 '<tt><span style="font-weight:bold;">123456789</span></tt>', 00308 '<tt><span style="font-weight:bold;">12***</span></tt>', 00309 ), 00310 array( 6, '***', 00311 '<p><a href="www.mediawiki.org">123456789</a></p>', 00312 '<p><a href="www.mediawiki.org">123***</a></p>', 00313 ), 00314 array( 6, '***', 00315 '<p><a href="www.mediawiki.org">12 456789</a></p>', 00316 '<p><a href="www.mediawiki.org">12 ***</a></p>', 00317 ), 00318 array( 7, '***', 00319 '<small><span style="font-weight:bold;">123<p id="#moo">456</p>789</span></small>', 00320 '<small><span style="font-weight:bold;">123<p id="#moo">4***</p></span></small>', 00321 ), 00322 array( 8, '***', 00323 '<div><span style="font-weight:bold;">123<span>4</span>56789</span></div>', 00324 '<div><span style="font-weight:bold;">123<span>4</span>5***</span></div>', 00325 ), 00326 array( 9, '***', 00327 '<p><table style="font-weight:bold;"><tr><td>123456789</td></tr></table></p>', 00328 '<p><table style="font-weight:bold;"><tr><td>123456789</td></tr></table></p>', 00329 ), 00330 array( 10, '***', 00331 '<p><font style="font-weight:bold;">123456789</font></p>', 00332 '<p><font style="font-weight:bold;">123456789</font></p>', 00333 ), 00334 ); 00335 } 00336 00342 public function testWellFormedLanguageTag( $code, $message = '' ) { 00343 $this->assertTrue( 00344 Language::isWellFormedLanguageTag( $code ), 00345 "validating code $code $message" 00346 ); 00347 } 00348 00355 public static function provideWellFormedLanguageTags() { 00356 return array( 00357 array( 'fr', 'two-letter code' ), 00358 array( 'fr-latn', 'two-letter code with lower case script code' ), 00359 array( 'fr-Latn-FR', 'two-letter code with title case script code and uppercase country code' ), 00360 array( 'fr-Latn-419', 'two-letter code with title case script code and region number' ), 00361 array( 'fr-FR', 'two-letter code with uppercase' ), 00362 array( 'ax-TZ', 'Not in the registry, but well-formed' ), 00363 array( 'fr-shadok', 'two-letter code with variant' ), 00364 array( 'fr-y-myext-myext2', 'non-x singleton' ), 00365 array( 'fra-Latn', 'ISO 639 can be 3-letters' ), 00366 array( 'fra', 'three-letter language code' ), 00367 array( 'fra-FX', 'three-letter language code with country code' ), 00368 array( 'i-klingon', 'grandfathered with singleton' ), 00369 array( 'I-kLINgon', 'tags are case-insensitive...' ), 00370 array( 'no-bok', 'grandfathered without singleton' ), 00371 array( 'i-enochian', 'Grandfathered' ), 00372 array( 'x-fr-CH', 'private use' ), 00373 array( 'es-419', 'two-letter code with region number' ), 00374 array( 'en-Latn-GB-boont-r-extended-sequence-x-private', 'weird, but well-formed' ), 00375 array( 'ab-x-abc-x-abc', 'anything goes after x' ), 00376 array( 'ab-x-abc-a-a', 'anything goes after x, including several non-x singletons' ), 00377 array( 'i-default', 'grandfathered' ), 00378 array( 'abcd-Latn', 'Language of 4 chars reserved for future use' ), 00379 array( 'AaBbCcDd-x-y-any-x', 'Language of 5-8 chars, registered' ), 00380 array( 'de-CH-1901', 'with country and year' ), 00381 array( 'en-US-x-twain', 'with country and singleton' ), 00382 array( 'zh-cmn', 'three-letter variant' ), 00383 array( 'zh-cmn-Hant', 'three-letter variant and script' ), 00384 array( 'zh-cmn-Hant-HK', 'three-letter variant, script and country' ), 00385 array( 'xr-p-lze', 'Extension' ), 00386 ); 00387 } 00388 00394 public function testMalformedLanguageTag( $code, $message = '' ) { 00395 $this->assertFalse( 00396 Language::isWellFormedLanguageTag( $code ), 00397 "validating that code $code is a malformed language tag - $message" 00398 ); 00399 } 00400 00407 public static function provideMalformedLanguageTags() { 00408 return array( 00409 array( 'f', 'language too short' ), 00410 array( 'f-Latn', 'language too short with script' ), 00411 array( 'xr-lxs-qut', 'variants too short' ), # extlangS 00412 array( 'fr-Latn-F', 'region too short' ), 00413 array( 'a-value', 'language too short with region' ), 00414 array( 'tlh-a-b-foo', 'valid three-letter with wrong variant' ), 00415 array( 00416 'i-notexist', 00417 'grandfathered but not registered: invalid, even if we only test well-formedness' 00418 ), 00419 array( 'abcdefghi-012345678', 'numbers too long' ), 00420 array( 'ab-abc-abc-abc-abc', 'invalid extensions' ), 00421 array( 'ab-abcd-abc', 'invalid extensions' ), 00422 array( 'ab-ab-abc', 'invalid extensions' ), 00423 array( 'ab-123-abc', 'invalid extensions' ), 00424 array( 'a-Hant-ZH', 'short language with valid extensions' ), 00425 array( 'a1-Hant-ZH', 'invalid character in language' ), 00426 array( 'ab-abcde-abc', 'invalid extensions' ), 00427 array( 'ab-1abc-abc', 'invalid characters in extensions' ), 00428 array( 'ab-ab-abcd', 'invalid order of extensions' ), 00429 array( 'ab-123-abcd', 'invalid order of extensions' ), 00430 array( 'ab-abcde-abcd', 'invalid extensions' ), 00431 array( 'ab-1abc-abcd', 'invalid characters in extensions' ), 00432 array( 'ab-a-b', 'extensions too short' ), 00433 array( 'ab-a-x', 'extensions too short, even with singleton' ), 00434 array( 'ab--ab', 'two separators' ), 00435 array( 'ab-abc-', 'separator in the end' ), 00436 array( '-ab-abc', 'separator in the beginning' ), 00437 array( 'abcd-efg', 'language too long' ), 00438 array( 'aabbccddE', 'tag too long' ), 00439 array( 'pa_guru', 'A tag with underscore is invalid in strict mode' ), 00440 array( 'de-f', 'subtag too short' ), 00441 ); 00442 } 00443 00448 public function testLenientLanguageTag() { 00449 $this->assertTrue( 00450 Language::isWellFormedLanguageTag( 'pa_guru', true ), 00451 'pa_guru is a well-formed language tag in lenient mode' 00452 ); 00453 } 00454 00460 public function testBuiltInCodeValidation( $code, $expected, $message = '' ) { 00461 $this->assertEquals( $expected, 00462 (bool)Language::isValidBuiltInCode( $code ), 00463 "validating code $code $message" 00464 ); 00465 } 00466 00467 public static function provideLanguageCodes() { 00468 return array( 00469 array( 'fr', true, 'Two letters, minor case' ), 00470 array( 'EN', false, 'Two letters, upper case' ), 00471 array( 'tyv', true, 'Three letters' ), 00472 array( 'tokipona', true, 'long language code' ), 00473 array( 'be-tarask', true, 'With dash' ), 00474 array( 'be-x-old', true, 'With extension (two dashes)' ), 00475 array( 'be_tarask', false, 'Reject underscores' ), 00476 ); 00477 } 00478 00484 public function testKnownLanguageTag( $code, $message = '' ) { 00485 $this->assertTrue( 00486 (bool)Language::isKnownLanguageTag( $code ), 00487 "validating code $code - $message" 00488 ); 00489 } 00490 00491 public static function provideKnownLanguageTags() { 00492 return array( 00493 array( 'fr', 'simple code' ), 00494 array( 'bat-smg', 'an MW legacy tag' ), 00495 array( 'sgs', 'an internal standard MW name, for which a legacy tag is used externally' ), 00496 ); 00497 } 00498 00502 public function testKnownCldrLanguageTag() { 00503 if ( !class_exists( 'LanguageNames' ) ) { 00504 $this->markTestSkipped( 'The LanguageNames class is not available. ' 00505 . 'The CLDR extension is probably not installed.' ); 00506 } 00507 00508 $this->assertTrue( 00509 (bool)Language::isKnownLanguageTag( 'pal' ), 00510 'validating code "pal" an ancient language, which probably will ' 00511 . 'not appear in Names.php, but appears in CLDR in English' 00512 ); 00513 } 00514 00520 public function testUnknownLanguageTag( $code, $message = '' ) { 00521 $this->assertFalse( 00522 (bool)Language::isKnownLanguageTag( $code ), 00523 "checking that code $code is invalid - $message" 00524 ); 00525 } 00526 00527 public static function provideUnknownLanguageTags() { 00528 return array( 00529 array( 'mw', 'non-existent two-letter code' ), 00530 array( 'foo"<bar', 'very invalid language code' ), 00531 ); 00532 } 00533 00539 public function testSprintfDateTooShortTimestamp() { 00540 $this->getLang()->sprintfDate( 'xiY', '1234567890123' ); 00541 } 00542 00548 public function testSprintfDateTooLongTimestamp() { 00549 $this->getLang()->sprintfDate( 'xiY', '123456789012345' ); 00550 } 00551 00557 public function testSprintfDateNotAllDigitTimestamp() { 00558 $this->getLang()->sprintfDate( 'xiY', '-1234567890123' ); 00559 } 00560 00565 public function testSprintfDate( $format, $ts, $expected, $msg ) { 00566 $ttl = null; 00567 $this->assertEquals( 00568 $expected, 00569 $this->getLang()->sprintfDate( $format, $ts, null, $ttl ), 00570 "sprintfDate('$format', '$ts'): $msg" 00571 ); 00572 if ( $ttl ) { 00573 $dt = new DateTime( $ts ); 00574 $lastValidTS = $dt->add( new DateInterval( 'PT' . ( $ttl - 1 ) . 'S' ) )->format( 'YmdHis' ); 00575 $this->assertEquals( 00576 $expected, 00577 $this->getLang()->sprintfDate( $format, $lastValidTS, null ), 00578 "sprintfDate('$format', '$ts'): TTL $ttl too high (output was different at $lastValidTS)" 00579 ); 00580 } else { 00581 // advance the time enough to make all of the possible outputs different (except possibly L) 00582 $dt = new DateTime( $ts ); 00583 $newTS = $dt->add( new DateInterval( 'P1Y1M8DT13H1M1S' ) )->format( 'YmdHis' ); 00584 $this->assertEquals( 00585 $expected, 00586 $this->getLang()->sprintfDate( $format, $newTS, null ), 00587 "sprintfDate('$format', '$ts'): Missing TTL (output was different at $newTS)" 00588 ); 00589 } 00590 } 00591 00597 public function testSprintfDateNoZone( $format, $ts, $expected, $ignore, $msg ) { 00598 $oldTZ = date_default_timezone_get(); 00599 $res = date_default_timezone_set( 'Asia/Seoul' ); 00600 if ( !$res ) { 00601 $this->markTestSkipped( "Error setting Timezone" ); 00602 } 00603 00604 $this->assertEquals( 00605 $expected, 00606 $this->getLang()->sprintfDate( $format, $ts ), 00607 "sprintfDate('$format', '$ts'): $msg" 00608 ); 00609 00610 date_default_timezone_set( $oldTZ ); 00611 } 00612 00618 public function testSprintfDateTZ( $format, $ts, $ignore, $expected, $msg ) { 00619 $tz = new DateTimeZone( 'Asia/Seoul' ); 00620 if ( !$tz ) { 00621 $this->markTestSkipped( "Error getting Timezone" ); 00622 } 00623 00624 $this->assertEquals( 00625 $expected, 00626 $this->getLang()->sprintfDate( $format, $ts, $tz ), 00627 "sprintfDate('$format', '$ts', 'Asia/Seoul'): $msg" 00628 ); 00629 } 00630 00631 public static function provideSprintfDateSamples() { 00632 return array( 00633 array( 00634 'xiY', 00635 '20111212000000', 00636 '1390', // note because we're testing English locale we get Latin-standard digits 00637 '1390', 00638 'Iranian calendar full year' 00639 ), 00640 array( 00641 'xiy', 00642 '20111212000000', 00643 '90', 00644 '90', 00645 'Iranian calendar short year' 00646 ), 00647 array( 00648 'o', 00649 '20120101235000', 00650 '2011', 00651 '2011', 00652 'ISO 8601 (week) year' 00653 ), 00654 array( 00655 'W', 00656 '20120101235000', 00657 '52', 00658 '52', 00659 'Week number' 00660 ), 00661 array( 00662 'W', 00663 '20120102235000', 00664 '1', 00665 '1', 00666 'Week number' 00667 ), 00668 array( 00669 'o-\\WW-N', 00670 '20091231235000', 00671 '2009-W53-4', 00672 '2009-W53-4', 00673 'leap week' 00674 ), 00675 // What follows is mostly copied from 00676 // https://www.mediawiki.org/wiki/Help:Extension:ParserFunctions#.23time 00677 array( 00678 'Y', 00679 '20120102090705', 00680 '2012', 00681 '2012', 00682 'Full year' 00683 ), 00684 array( 00685 'y', 00686 '20120102090705', 00687 '12', 00688 '12', 00689 '2 digit year' 00690 ), 00691 array( 00692 'L', 00693 '20120102090705', 00694 '1', 00695 '1', 00696 'Leap year' 00697 ), 00698 array( 00699 'n', 00700 '20120102090705', 00701 '1', 00702 '1', 00703 'Month index, not zero pad' 00704 ), 00705 array( 00706 'N', 00707 '20120102090705', 00708 '01', 00709 '01', 00710 'Month index. Zero pad' 00711 ), 00712 array( 00713 'M', 00714 '20120102090705', 00715 'Jan', 00716 'Jan', 00717 'Month abbrev' 00718 ), 00719 array( 00720 'F', 00721 '20120102090705', 00722 'January', 00723 'January', 00724 'Full month' 00725 ), 00726 array( 00727 'xg', 00728 '20120102090705', 00729 'January', 00730 'January', 00731 'Genitive month name (same in EN)' 00732 ), 00733 array( 00734 'j', 00735 '20120102090705', 00736 '2', 00737 '2', 00738 'Day of month (not zero pad)' 00739 ), 00740 array( 00741 'd', 00742 '20120102090705', 00743 '02', 00744 '02', 00745 'Day of month (zero-pad)' 00746 ), 00747 array( 00748 'z', 00749 '20120102090705', 00750 '1', 00751 '1', 00752 'Day of year (zero-indexed)' 00753 ), 00754 array( 00755 'D', 00756 '20120102090705', 00757 'Mon', 00758 'Mon', 00759 'Day of week (abbrev)' 00760 ), 00761 array( 00762 'l', 00763 '20120102090705', 00764 'Monday', 00765 'Monday', 00766 'Full day of week' 00767 ), 00768 array( 00769 'N', 00770 '20120101090705', 00771 '7', 00772 '7', 00773 'Day of week (Mon=1, Sun=7)' 00774 ), 00775 array( 00776 'w', 00777 '20120101090705', 00778 '0', 00779 '0', 00780 'Day of week (Sun=0, Sat=6)' 00781 ), 00782 array( 00783 'N', 00784 '20120102090705', 00785 '1', 00786 '1', 00787 'Day of week' 00788 ), 00789 array( 00790 'a', 00791 '20120102090705', 00792 'am', 00793 'am', 00794 'am vs pm' 00795 ), 00796 array( 00797 'A', 00798 '20120102120000', 00799 'PM', 00800 'PM', 00801 'AM vs PM' 00802 ), 00803 array( 00804 'a', 00805 '20120102000000', 00806 'am', 00807 'am', 00808 'AM vs PM' 00809 ), 00810 array( 00811 'g', 00812 '20120102090705', 00813 '9', 00814 '9', 00815 '12 hour, not Zero' 00816 ), 00817 array( 00818 'h', 00819 '20120102090705', 00820 '09', 00821 '09', 00822 '12 hour, zero padded' 00823 ), 00824 array( 00825 'G', 00826 '20120102090705', 00827 '9', 00828 '9', 00829 '24 hour, not zero' 00830 ), 00831 array( 00832 'H', 00833 '20120102090705', 00834 '09', 00835 '09', 00836 '24 hour, zero' 00837 ), 00838 array( 00839 'H', 00840 '20120102110705', 00841 '11', 00842 '11', 00843 '24 hour, zero' 00844 ), 00845 array( 00846 'i', 00847 '20120102090705', 00848 '07', 00849 '07', 00850 'Minutes' 00851 ), 00852 array( 00853 's', 00854 '20120102090705', 00855 '05', 00856 '05', 00857 'seconds' 00858 ), 00859 array( 00860 'U', 00861 '20120102090705', 00862 '1325495225', 00863 '1325462825', 00864 'unix time' 00865 ), 00866 array( 00867 't', 00868 '20120102090705', 00869 '31', 00870 '31', 00871 'Days in current month' 00872 ), 00873 array( 00874 'c', 00875 '20120102090705', 00876 '2012-01-02T09:07:05+00:00', 00877 '2012-01-02T09:07:05+09:00', 00878 'ISO 8601 timestamp' 00879 ), 00880 array( 00881 'r', 00882 '20120102090705', 00883 'Mon, 02 Jan 2012 09:07:05 +0000', 00884 'Mon, 02 Jan 2012 09:07:05 +0900', 00885 'RFC 5322' 00886 ), 00887 array( 00888 'e', 00889 '20120102090705', 00890 'UTC', 00891 'Asia/Seoul', 00892 'Timezone identifier' 00893 ), 00894 array( 00895 'I', 00896 '19880602090705', 00897 '0', 00898 '1', 00899 'DST indicator' 00900 ), 00901 array( 00902 'O', 00903 '20120102090705', 00904 '+0000', 00905 '+0900', 00906 'Timezone offset' 00907 ), 00908 array( 00909 'P', 00910 '20120102090705', 00911 '+00:00', 00912 '+09:00', 00913 'Timezone offset with colon' 00914 ), 00915 array( 00916 'T', 00917 '20120102090705', 00918 'UTC', 00919 'KST', 00920 'Timezone abbreviation' 00921 ), 00922 array( 00923 'Z', 00924 '20120102090705', 00925 '0', 00926 '32400', 00927 'Timezone offset in seconds' 00928 ), 00929 array( 00930 'xmj xmF xmn xmY', 00931 '20120102090705', 00932 '7 Safar 2 1433', 00933 '7 Safar 2 1433', 00934 'Islamic' 00935 ), 00936 array( 00937 'xij xiF xin xiY', 00938 '20120102090705', 00939 '12 Dey 10 1390', 00940 '12 Dey 10 1390', 00941 'Iranian' 00942 ), 00943 array( 00944 'xjj xjF xjn xjY', 00945 '20120102090705', 00946 '7 Tevet 4 5772', 00947 '7 Tevet 4 5772', 00948 'Hebrew' 00949 ), 00950 array( 00951 'xjt', 00952 '20120102090705', 00953 '29', 00954 '29', 00955 'Hebrew number of days in month' 00956 ), 00957 array( 00958 'xjx', 00959 '20120102090705', 00960 'Tevet', 00961 'Tevet', 00962 'Hebrew genitive month name (No difference in EN)' 00963 ), 00964 array( 00965 'xkY', 00966 '20120102090705', 00967 '2555', 00968 '2555', 00969 'Thai year' 00970 ), 00971 array( 00972 'xoY', 00973 '20120102090705', 00974 '101', 00975 '101', 00976 'Minguo' 00977 ), 00978 array( 00979 'xtY', 00980 '20120102090705', 00981 '平成24', 00982 '平成24', 00983 'nengo' 00984 ), 00985 array( 00986 'xrxkYY', 00987 '20120102090705', 00988 'MMDLV2012', 00989 'MMDLV2012', 00990 'Roman numerals' 00991 ), 00992 array( 00993 'xhxjYY', 00994 '20120102090705', 00995 'ה\'תשע"ב2012', 00996 'ה\'תשע"ב2012', 00997 'Hebrew numberals' 00998 ), 00999 array( 01000 'xnY', 01001 '20120102090705', 01002 '2012', 01003 '2012', 01004 'Raw numerals (doesn\'t mean much in EN)' 01005 ), 01006 array( 01007 '[[Y "(yea"\\r)]] \\"xx\\"', 01008 '20120102090705', 01009 '[[2012 (year)]] "x"', 01010 '[[2012 (year)]] "x"', 01011 'Various escaping' 01012 ), 01013 01014 ); 01015 } 01016 01021 public function testFormatSize( $size, $expected, $msg ) { 01022 $this->assertEquals( 01023 $expected, 01024 $this->getLang()->formatSize( $size ), 01025 "formatSize('$size'): $msg" 01026 ); 01027 } 01028 01029 public static function provideFormatSizes() { 01030 return array( 01031 array( 01032 0, 01033 "0 B", 01034 "Zero bytes" 01035 ), 01036 array( 01037 1024, 01038 "1 KB", 01039 "1 kilobyte" 01040 ), 01041 array( 01042 1024 * 1024, 01043 "1 MB", 01044 "1,024 megabytes" 01045 ), 01046 array( 01047 1024 * 1024 * 1024, 01048 "1 GB", 01049 "1 gigabytes" 01050 ), 01051 array( 01052 pow( 1024, 4 ), 01053 "1 TB", 01054 "1 terabyte" 01055 ), 01056 array( 01057 pow( 1024, 5 ), 01058 "1 PB", 01059 "1 petabyte" 01060 ), 01061 array( 01062 pow( 1024, 6 ), 01063 "1 EB", 01064 "1,024 exabyte" 01065 ), 01066 array( 01067 pow( 1024, 7 ), 01068 "1 ZB", 01069 "1 zetabyte" 01070 ), 01071 array( 01072 pow( 1024, 8 ), 01073 "1 YB", 01074 "1 yottabyte" 01075 ), 01076 // How big!? THIS BIG! 01077 ); 01078 } 01079 01084 public function testFormatBitrate( $bps, $expected, $msg ) { 01085 $this->assertEquals( 01086 $expected, 01087 $this->getLang()->formatBitrate( $bps ), 01088 "formatBitrate('$bps'): $msg" 01089 ); 01090 } 01091 01092 public static function provideFormatBitrate() { 01093 return array( 01094 array( 01095 0, 01096 "0 bps", 01097 "0 bits per second" 01098 ), 01099 array( 01100 999, 01101 "999 bps", 01102 "999 bits per second" 01103 ), 01104 array( 01105 1000, 01106 "1 kbps", 01107 "1 kilobit per second" 01108 ), 01109 array( 01110 1000 * 1000, 01111 "1 Mbps", 01112 "1 megabit per second" 01113 ), 01114 array( 01115 pow( 10, 9 ), 01116 "1 Gbps", 01117 "1 gigabit per second" 01118 ), 01119 array( 01120 pow( 10, 12 ), 01121 "1 Tbps", 01122 "1 terabit per second" 01123 ), 01124 array( 01125 pow( 10, 15 ), 01126 "1 Pbps", 01127 "1 petabit per second" 01128 ), 01129 array( 01130 pow( 10, 18 ), 01131 "1 Ebps", 01132 "1 exabit per second" 01133 ), 01134 array( 01135 pow( 10, 21 ), 01136 "1 Zbps", 01137 "1 zetabit per second" 01138 ), 01139 array( 01140 pow( 10, 24 ), 01141 "1 Ybps", 01142 "1 yottabit per second" 01143 ), 01144 array( 01145 pow( 10, 27 ), 01146 "1,000 Ybps", 01147 "1,000 yottabits per second" 01148 ), 01149 ); 01150 } 01151 01156 public function testFormatDuration( $duration, $expected, $intervals = array() ) { 01157 $this->assertEquals( 01158 $expected, 01159 $this->getLang()->formatDuration( $duration, $intervals ), 01160 "formatDuration('$duration'): $expected" 01161 ); 01162 } 01163 01164 public static function provideFormatDuration() { 01165 return array( 01166 array( 01167 0, 01168 '0 seconds', 01169 ), 01170 array( 01171 1, 01172 '1 second', 01173 ), 01174 array( 01175 2, 01176 '2 seconds', 01177 ), 01178 array( 01179 60, 01180 '1 minute', 01181 ), 01182 array( 01183 2 * 60, 01184 '2 minutes', 01185 ), 01186 array( 01187 3600, 01188 '1 hour', 01189 ), 01190 array( 01191 2 * 3600, 01192 '2 hours', 01193 ), 01194 array( 01195 24 * 3600, 01196 '1 day', 01197 ), 01198 array( 01199 2 * 86400, 01200 '2 days', 01201 ), 01202 array( 01203 // ( 365 + ( 24 * 3 + 25 ) / 400 ) * 86400 = 31556952 01204 ( 365 + ( 24 * 3 + 25 ) / 400.0 ) * 86400, 01205 '1 year', 01206 ), 01207 array( 01208 2 * 31556952, 01209 '2 years', 01210 ), 01211 array( 01212 10 * 31556952, 01213 '1 decade', 01214 ), 01215 array( 01216 20 * 31556952, 01217 '2 decades', 01218 ), 01219 array( 01220 100 * 31556952, 01221 '1 century', 01222 ), 01223 array( 01224 200 * 31556952, 01225 '2 centuries', 01226 ), 01227 array( 01228 1000 * 31556952, 01229 '1 millennium', 01230 ), 01231 array( 01232 2000 * 31556952, 01233 '2 millennia', 01234 ), 01235 array( 01236 9001, 01237 '2 hours, 30 minutes and 1 second' 01238 ), 01239 array( 01240 3601, 01241 '1 hour and 1 second' 01242 ), 01243 array( 01244 31556952 + 2 * 86400 + 9000, 01245 '1 year, 2 days, 2 hours and 30 minutes' 01246 ), 01247 array( 01248 42 * 1000 * 31556952 + 42, 01249 '42 millennia and 42 seconds' 01250 ), 01251 array( 01252 60, 01253 '60 seconds', 01254 array( 'seconds' ), 01255 ), 01256 array( 01257 61, 01258 '61 seconds', 01259 array( 'seconds' ), 01260 ), 01261 array( 01262 1, 01263 '1 second', 01264 array( 'seconds' ), 01265 ), 01266 array( 01267 31556952 + 2 * 86400 + 9000, 01268 '1 year, 2 days and 150 minutes', 01269 array( 'years', 'days', 'minutes' ), 01270 ), 01271 array( 01272 42, 01273 '0 days', 01274 array( 'years', 'days' ), 01275 ), 01276 array( 01277 31556952 + 2 * 86400 + 9000, 01278 '1 year, 2 days and 150 minutes', 01279 array( 'minutes', 'days', 'years' ), 01280 ), 01281 array( 01282 42, 01283 '0 days', 01284 array( 'days', 'years' ), 01285 ), 01286 ); 01287 } 01288 01293 public function testCheckTitleEncoding( $s ) { 01294 $this->assertEquals( 01295 $s, 01296 $this->getLang()->checkTitleEncoding( $s ), 01297 "checkTitleEncoding('$s')" 01298 ); 01299 } 01300 01301 public static function provideCheckTitleEncodingData() { 01302 // @codingStandardsIgnoreStart Ignore Generic.Files.LineLength.TooLong 01303 return array( 01304 array( "" ), 01305 array( "United States of America" ), // 7bit ASCII 01306 array( rawurldecode( "S%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e" ) ), 01307 array( 01308 rawurldecode( 01309 "Acteur%7CAlbert%20Robbins%7CAnglais%7CAnn%20Donahue%7CAnthony%20E.%20Zuiker%7CCarol%20Mendelsohn" 01310 ) 01311 ), 01312 // The following two data sets come from bug 36839. They fail if checkTitleEncoding uses a regexp to test for 01313 // valid UTF-8 encoding and the pcre.recursion_limit is low (like, say, 1024). They succeed if checkTitleEncoding 01314 // uses mb_check_encoding for its test. 01315 array( 01316 rawurldecode( 01317 "Acteur%7CAlbert%20Robbins%7CAnglais%7CAnn%20Donahue%7CAnthony%20E.%20Zuiker%7CCarol%20Mendelsohn%7C" 01318 . "Catherine%20Willows%7CDavid%20Hodges%7CDavid%20Phillips%7CGil%20Grissom%7CGreg%20Sanders%7CHodges%7C" 01319 . "Internet%20Movie%20Database%7CJim%20Brass%7CLady%20Heather%7C" 01320 . "Les%20Experts%20(s%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e)%7CLes%20Experts%20:%20Manhattan%7C" 01321 . "Les%20Experts%20:%20Miami%7CListe%20des%20personnages%20des%20Experts%7C" 01322 . "Liste%20des%20%C3%A9pisodes%20des%20Experts%7CMod%C3%A8le%20discussion:Palette%20Les%20Experts%7C" 01323 . "Nick%20Stokes%7CPersonnage%20de%20fiction%7CPersonnage%20fictif%7CPersonnage%20de%20fiction%7C" 01324 . "Personnages%20r%C3%A9currents%20dans%20Les%20Experts%7CRaymond%20Langston%7CRiley%20Adams%7C" 01325 . "Saison%201%20des%20Experts%7CSaison%2010%20des%20Experts%7CSaison%2011%20des%20Experts%7C" 01326 . "Saison%2012%20des%20Experts%7CSaison%202%20des%20Experts%7CSaison%203%20des%20Experts%7C" 01327 . "Saison%204%20des%20Experts%7CSaison%205%20des%20Experts%7CSaison%206%20des%20Experts%7C" 01328 . "Saison%207%20des%20Experts%7CSaison%208%20des%20Experts%7CSaison%209%20des%20Experts%7C" 01329 . "Sara%20Sidle%7CSofia%20Curtis%7CS%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e%7CWallace%20Langham%7C" 01330 . "Warrick%20Brown%7CWendy%20Simms%7C%C3%89tats-Unis" 01331 ), 01332 ), 01333 array( 01334 rawurldecode( 01335 "Mod%C3%A8le%3AArrondissements%20homonymes%7CMod%C3%A8le%3ABandeau%20standard%20pour%20page%20d'homonymie%7C" 01336 . "Mod%C3%A8le%3ABatailles%20homonymes%7CMod%C3%A8le%3ACantons%20homonymes%7C" 01337 . "Mod%C3%A8le%3ACommunes%20fran%C3%A7aises%20homonymes%7CMod%C3%A8le%3AFilms%20homonymes%7C" 01338 . "Mod%C3%A8le%3AGouvernements%20homonymes%7CMod%C3%A8le%3AGuerres%20homonymes%7CMod%C3%A8le%3AHomonymie%7C" 01339 . "Mod%C3%A8le%3AHomonymie%20bateau%7CMod%C3%A8le%3AHomonymie%20d'%C3%A9tablissements%20scolaires%20ou" 01340 . "%20universitaires%7CMod%C3%A8le%3AHomonymie%20d'%C3%AEles%7CMod%C3%A8le%3AHomonymie%20de%20clubs%20sportifs%7C" 01341 . "Mod%C3%A8le%3AHomonymie%20de%20comt%C3%A9s%7CMod%C3%A8le%3AHomonymie%20de%20monument%7C" 01342 . "Mod%C3%A8le%3AHomonymie%20de%20nom%20romain%7CMod%C3%A8le%3AHomonymie%20de%20parti%20politique%7C" 01343 . "Mod%C3%A8le%3AHomonymie%20de%20route%7CMod%C3%A8le%3AHomonymie%20dynastique%7C" 01344 . "Mod%C3%A8le%3AHomonymie%20vid%C3%A9oludique%7CMod%C3%A8le%3AHomonymie%20%C3%A9difice%20religieux%7C" 01345 . "Mod%C3%A8le%3AInternationalisation%7CMod%C3%A8le%3AIsom%C3%A9rie%7CMod%C3%A8le%3AParonymie%7C" 01346 . "Mod%C3%A8le%3APatronyme%7CMod%C3%A8le%3APatronyme%20basque%7CMod%C3%A8le%3APatronyme%20italien%7C" 01347 . "Mod%C3%A8le%3APatronymie%7CMod%C3%A8le%3APersonnes%20homonymes%7CMod%C3%A8le%3ASaints%20homonymes%7C" 01348 . "Mod%C3%A8le%3ATitres%20homonymes%7CMod%C3%A8le%3AToponymie%7CMod%C3%A8le%3AUnit%C3%A9s%20homonymes%7C" 01349 . "Mod%C3%A8le%3AVilles%20homonymes%7CMod%C3%A8le%3A%C3%89difices%20religieux%20homonymes" 01350 ) 01351 ) 01352 ); 01353 // @codingStandardsIgnoreEnd 01354 } 01355 01360 public function testRomanNumerals( $num, $numerals ) { 01361 $this->assertEquals( 01362 $numerals, 01363 Language::romanNumeral( $num ), 01364 "romanNumeral('$num')" 01365 ); 01366 } 01367 01368 public static function provideRomanNumeralsData() { 01369 return array( 01370 array( 1, 'I' ), 01371 array( 2, 'II' ), 01372 array( 3, 'III' ), 01373 array( 4, 'IV' ), 01374 array( 5, 'V' ), 01375 array( 6, 'VI' ), 01376 array( 7, 'VII' ), 01377 array( 8, 'VIII' ), 01378 array( 9, 'IX' ), 01379 array( 10, 'X' ), 01380 array( 20, 'XX' ), 01381 array( 30, 'XXX' ), 01382 array( 40, 'XL' ), 01383 array( 49, 'XLIX' ), 01384 array( 50, 'L' ), 01385 array( 60, 'LX' ), 01386 array( 70, 'LXX' ), 01387 array( 80, 'LXXX' ), 01388 array( 90, 'XC' ), 01389 array( 99, 'XCIX' ), 01390 array( 100, 'C' ), 01391 array( 200, 'CC' ), 01392 array( 300, 'CCC' ), 01393 array( 400, 'CD' ), 01394 array( 500, 'D' ), 01395 array( 600, 'DC' ), 01396 array( 700, 'DCC' ), 01397 array( 800, 'DCCC' ), 01398 array( 900, 'CM' ), 01399 array( 999, 'CMXCIX' ), 01400 array( 1000, 'M' ), 01401 array( 1989, 'MCMLXXXIX' ), 01402 array( 2000, 'MM' ), 01403 array( 3000, 'MMM' ), 01404 array( 4000, 'MMMM' ), 01405 array( 5000, 'MMMMM' ), 01406 array( 6000, 'MMMMMM' ), 01407 array( 7000, 'MMMMMMM' ), 01408 array( 8000, 'MMMMMMMM' ), 01409 array( 9000, 'MMMMMMMMM' ), 01410 array( 9999, 'MMMMMMMMMCMXCIX' ), 01411 array( 10000, 'MMMMMMMMMM' ), 01412 ); 01413 } 01414 01419 public function testConvertPlural( $expected, $number, $forms ) { 01420 $chosen = $this->getLang()->convertPlural( $number, $forms ); 01421 $this->assertEquals( $expected, $chosen ); 01422 } 01423 01424 public static function providePluralData() { 01425 // Params are: [expected text, number given, [the plural forms]] 01426 return array( 01427 array( 'plural', 0, array( 01428 'singular', 'plural' 01429 ) ), 01430 array( 'explicit zero', 0, array( 01431 '0=explicit zero', 'singular', 'plural' 01432 ) ), 01433 array( 'explicit one', 1, array( 01434 'singular', 'plural', '1=explicit one', 01435 ) ), 01436 array( 'singular', 1, array( 01437 'singular', 'plural', '0=explicit zero', 01438 ) ), 01439 array( 'plural', 3, array( 01440 '0=explicit zero', '1=explicit one', 'singular', 'plural' 01441 ) ), 01442 array( 'explicit eleven', 11, array( 01443 'singular', 'plural', '11=explicit eleven', 01444 ) ), 01445 array( 'plural', 12, array( 01446 'singular', 'plural', '11=explicit twelve', 01447 ) ), 01448 array( 'plural', 12, array( 01449 'singular', 'plural', '=explicit form', 01450 ) ), 01451 array( 'other', 2, array( 01452 'kissa=kala', '1=2=3', 'other', 01453 ) ), 01454 array( '', 2, array( 01455 '0=explicit zero', '1=explicit one', 01456 ) ), 01457 ); 01458 } 01459 01464 public function testTranslateBlockExpiry( $expectedData, $str, $desc ) { 01465 $lang = $this->getLang(); 01466 if ( is_array( $expectedData ) ) { 01467 list( $func, $arg ) = $expectedData; 01468 $expected = $lang->$func( $arg ); 01469 } else { 01470 $expected = $expectedData; 01471 } 01472 $this->assertEquals( $expected, $lang->translateBlockExpiry( $str ), $desc ); 01473 } 01474 01475 public static function provideTranslateBlockExpiry() { 01476 return array( 01477 array( '2 hours', '2 hours', 'simple data from ipboptions' ), 01478 array( 'indefinite', 'infinite', 'infinite from ipboptions' ), 01479 array( 'indefinite', 'infinity', 'alternative infinite from ipboptions' ), 01480 array( 'indefinite', 'indefinite', 'another alternative infinite from ipboptions' ), 01481 array( array( 'formatDuration', 1023 * 60 * 60 ), '1023 hours', 'relative' ), 01482 array( array( 'formatDuration', -1023 ), '-1023 seconds', 'negative relative' ), 01483 array( array( 'formatDuration', 0 ), 'now', 'now' ), 01484 array( 01485 array( 'timeanddate', '20120102070000' ), 01486 '2012-1-1 7:00 +1 day', 01487 'mixed, handled as absolute' 01488 ), 01489 array( array( 'timeanddate', '19910203040506' ), '1991-2-3 4:05:06', 'absolute' ), 01490 array( array( 'timeanddate', '19700101000000' ), '1970-1-1 0:00:00', 'absolute at epoch' ), 01491 array( array( 'timeanddate', '19691231235959' ), '1969-12-31 23:59:59', 'time before epoch' ), 01492 array( 'dummy', 'dummy', 'return garbage as is' ), 01493 ); 01494 } 01495 01499 public function testParseFormattedNumber( $langCode, $number ) { 01500 $lang = Language::factory( $langCode ); 01501 01502 $localisedNum = $lang->formatNum( $number ); 01503 $normalisedNum = $lang->parseFormattedNumber( $localisedNum ); 01504 01505 $this->assertEquals( $number, $normalisedNum ); 01506 } 01507 01508 public function parseFormattedNumberProvider() { 01509 return array( 01510 array( 'de', 377.01 ), 01511 array( 'fa', 334 ), 01512 array( 'fa', 382.772 ), 01513 array( 'ar', 1844 ), 01514 array( 'lzh', 3731 ), 01515 array( 'zh-classical', 7432 ) 01516 ); 01517 } 01518 01523 public function testCommafy( $number, $numbersWithCommas ) { 01524 $this->assertEquals( 01525 $numbersWithCommas, 01526 $this->getLang()->commafy( $number ), 01527 "commafy('$number')" 01528 ); 01529 } 01530 01531 public static function provideCommafyData() { 01532 return array( 01533 array( -1, '-1' ), 01534 array( 10, '10' ), 01535 array( 100, '100' ), 01536 array( 1000, '1,000' ), 01537 array( 10000, '10,000' ), 01538 array( 100000, '100,000' ), 01539 array( 1000000, '1,000,000' ), 01540 array( -1.0001, '-1.0001' ), 01541 array( 1.0001, '1.0001' ), 01542 array( 10.0001, '10.0001' ), 01543 array( 100.0001, '100.0001' ), 01544 array( 1000.0001, '1,000.0001' ), 01545 array( 10000.0001, '10,000.0001' ), 01546 array( 100000.0001, '100,000.0001' ), 01547 array( 1000000.0001, '1,000,000.0001' ), 01548 array( '200000000000000000000', '200,000,000,000,000,000,000' ), 01549 array( '-200000000000000000000', '-200,000,000,000,000,000,000' ), 01550 ); 01551 } 01552 01556 public function testListToText() { 01557 $lang = $this->getLang(); 01558 $and = $lang->getMessageFromDB( 'and' ); 01559 $s = $lang->getMessageFromDB( 'word-separator' ); 01560 $c = $lang->getMessageFromDB( 'comma-separator' ); 01561 01562 $this->assertEquals( '', $lang->listToText( array() ) ); 01563 $this->assertEquals( 'a', $lang->listToText( array( 'a' ) ) ); 01564 $this->assertEquals( "a{$and}{$s}b", $lang->listToText( array( 'a', 'b' ) ) ); 01565 $this->assertEquals( "a{$c}b{$and}{$s}c", $lang->listToText( array( 'a', 'b', 'c' ) ) ); 01566 $this->assertEquals( "a{$c}b{$c}c{$and}{$s}d", $lang->listToText( array( 'a', 'b', 'c', 'd' ) ) ); 01567 } 01568 01573 public function testIsSupportedLanguage( $code, $expected, $comment ) { 01574 $this->assertEquals( $expected, Language::isSupportedLanguage( $code ), $comment ); 01575 } 01576 01577 public static function provideIsSupportedLanguage() { 01578 return array( 01579 array( 'en', true, 'is supported language' ), 01580 array( 'fi', true, 'is supported language' ), 01581 array( 'bunny', false, 'is not supported language' ), 01582 array( 'FI', false, 'is not supported language, input should be in lower case' ), 01583 ); 01584 } 01585 01590 public function testGetParentLanguage( $code, $expected, $comment ) { 01591 $lang = Language::factory( $code ); 01592 if ( is_null( $expected ) ) { 01593 $this->assertNull( $lang->getParentLanguage(), $comment ); 01594 } else { 01595 $this->assertEquals( $expected, $lang->getParentLanguage()->getCode(), $comment ); 01596 } 01597 } 01598 01599 public static function provideGetParentLanguage() { 01600 return array( 01601 array( 'zh-cn', 'zh', 'zh is the parent language of zh-cn' ), 01602 array( 'zh', 'zh', 'zh is defined as the parent language of zh, ' 01603 . 'because zh converter can convert zh-cn to zh' ), 01604 array( 'zh-invalid', null, 'do not be fooled by arbitrarily composed language codes' ), 01605 array( 'en-gb', null, 'en does not have converter' ), 01606 array( 'en', null, 'en does not have converter. Although FakeConverter ' 01607 . 'handles en -> en conversion but it is useless' ), 01608 ); 01609 } 01610 01615 public function testGetNamespaceAliases( $languageCode, $subset ) { 01616 $language = Language::factory( $languageCode ); 01617 $aliases = $language->getNamespaceAliases(); 01618 foreach ( $subset as $alias => $nsId ) { 01619 $this->assertEquals( $nsId, $aliases[$alias] ); 01620 } 01621 } 01622 01623 public static function provideGetNamespaceAliases() { 01624 // TODO: Add tests for NS_PROJECT_TALK and GenderNamespaces 01625 return array( 01626 array( 01627 'zh', 01628 array( 01629 '文件' => NS_FILE, 01630 '檔案' => NS_FILE, 01631 ), 01632 ), 01633 ); 01634 } 01635 }