1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897 |
- <?php
- use Wikimedia\TestingAccessWrapper;
- class LanguageTest extends LanguageClassesTestCase {
- /**
- * @covers Language::convertDoubleWidth
- * @covers Language::normalizeForSearch
- */
- public function testLanguageConvertDoubleWidthToSingleWidth() {
- $this->assertEquals(
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
- $this->getLang()->normalizeForSearch(
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
- ),
- 'convertDoubleWidth() with the full alphabet and digits'
- );
- }
- /**
- * @dataProvider provideFormattableTimes
- * @covers Language::formatTimePeriod
- */
- public function testFormatTimePeriod( $seconds, $format, $expected, $desc ) {
- $this->assertEquals( $expected, $this->getLang()->formatTimePeriod( $seconds, $format ), $desc );
- }
- public static function provideFormattableTimes() {
- return [
- [
- 9.45,
- [],
- '9.5 s',
- 'formatTimePeriod() rounding (<10s)'
- ],
- [
- 9.45,
- [ 'noabbrevs' => true ],
- '9.5 seconds',
- 'formatTimePeriod() rounding (<10s)'
- ],
- [
- 9.95,
- [],
- '10 s',
- 'formatTimePeriod() rounding (<10s)'
- ],
- [
- 9.95,
- [ 'noabbrevs' => true ],
- '10 seconds',
- 'formatTimePeriod() rounding (<10s)'
- ],
- [
- 59.55,
- [],
- '1 min 0 s',
- 'formatTimePeriod() rounding (<60s)'
- ],
- [
- 59.55,
- [ 'noabbrevs' => true ],
- '1 minute 0 seconds',
- 'formatTimePeriod() rounding (<60s)'
- ],
- [
- 119.55,
- [],
- '2 min 0 s',
- 'formatTimePeriod() rounding (<1h)'
- ],
- [
- 119.55,
- [ 'noabbrevs' => true ],
- '2 minutes 0 seconds',
- 'formatTimePeriod() rounding (<1h)'
- ],
- [
- 3599.55,
- [],
- '1 h 0 min 0 s',
- 'formatTimePeriod() rounding (<1h)'
- ],
- [
- 3599.55,
- [ 'noabbrevs' => true ],
- '1 hour 0 minutes 0 seconds',
- 'formatTimePeriod() rounding (<1h)'
- ],
- [
- 7199.55,
- [],
- '2 h 0 min 0 s',
- 'formatTimePeriod() rounding (>=1h)'
- ],
- [
- 7199.55,
- [ 'noabbrevs' => true ],
- '2 hours 0 minutes 0 seconds',
- 'formatTimePeriod() rounding (>=1h)'
- ],
- [
- 7199.55,
- 'avoidseconds',
- '2 h 0 min',
- 'formatTimePeriod() rounding (>=1h), avoidseconds'
- ],
- [
- 7199.55,
- [ 'avoid' => 'avoidseconds', 'noabbrevs' => true ],
- '2 hours 0 minutes',
- 'formatTimePeriod() rounding (>=1h), avoidseconds'
- ],
- [
- 7199.55,
- 'avoidminutes',
- '2 h 0 min',
- 'formatTimePeriod() rounding (>=1h), avoidminutes'
- ],
- [
- 7199.55,
- [ 'avoid' => 'avoidminutes', 'noabbrevs' => true ],
- '2 hours 0 minutes',
- 'formatTimePeriod() rounding (>=1h), avoidminutes'
- ],
- [
- 172799.55,
- 'avoidseconds',
- '48 h 0 min',
- 'formatTimePeriod() rounding (=48h), avoidseconds'
- ],
- [
- 172799.55,
- [ 'avoid' => 'avoidseconds', 'noabbrevs' => true ],
- '48 hours 0 minutes',
- 'formatTimePeriod() rounding (=48h), avoidseconds'
- ],
- [
- 259199.55,
- 'avoidminutes',
- '3 d 0 h',
- 'formatTimePeriod() rounding (>48h), avoidminutes'
- ],
- [
- 259199.55,
- [ 'avoid' => 'avoidminutes', 'noabbrevs' => true ],
- '3 days 0 hours',
- 'formatTimePeriod() rounding (>48h), avoidminutes'
- ],
- [
- 176399.55,
- 'avoidseconds',
- '2 d 1 h 0 min',
- 'formatTimePeriod() rounding (>48h), avoidseconds'
- ],
- [
- 176399.55,
- [ 'avoid' => 'avoidseconds', 'noabbrevs' => true ],
- '2 days 1 hour 0 minutes',
- 'formatTimePeriod() rounding (>48h), avoidseconds'
- ],
- [
- 176399.55,
- 'avoidminutes',
- '2 d 1 h',
- 'formatTimePeriod() rounding (>48h), avoidminutes'
- ],
- [
- 176399.55,
- [ 'avoid' => 'avoidminutes', 'noabbrevs' => true ],
- '2 days 1 hour',
- 'formatTimePeriod() rounding (>48h), avoidminutes'
- ],
- [
- 259199.55,
- 'avoidseconds',
- '3 d 0 h 0 min',
- 'formatTimePeriod() rounding (>48h), avoidseconds'
- ],
- [
- 259199.55,
- [ 'avoid' => 'avoidseconds', 'noabbrevs' => true ],
- '3 days 0 hours 0 minutes',
- 'formatTimePeriod() rounding (>48h), avoidseconds'
- ],
- [
- 172801.55,
- 'avoidseconds',
- '2 d 0 h 0 min',
- 'formatTimePeriod() rounding, (>48h), avoidseconds'
- ],
- [
- 172801.55,
- [ 'avoid' => 'avoidseconds', 'noabbrevs' => true ],
- '2 days 0 hours 0 minutes',
- 'formatTimePeriod() rounding, (>48h), avoidseconds'
- ],
- [
- 176460.55,
- [],
- '2 d 1 h 1 min 1 s',
- 'formatTimePeriod() rounding, recursion, (>48h)'
- ],
- [
- 176460.55,
- [ 'noabbrevs' => true ],
- '2 days 1 hour 1 minute 1 second',
- 'formatTimePeriod() rounding, recursion, (>48h)'
- ],
- ];
- }
- /**
- * @covers Language::truncateForDatabase
- * @covers Language::truncateInternal
- */
- public function testTruncateForDatabase() {
- $this->assertEquals(
- "XXX",
- $this->getLang()->truncateForDatabase( "1234567890", 0, 'XXX' ),
- 'truncate prefix, len 0, small ellipsis'
- );
- $this->assertEquals(
- "12345XXX",
- $this->getLang()->truncateForDatabase( "1234567890", 8, 'XXX' ),
- 'truncate prefix, small ellipsis'
- );
- $this->assertEquals(
- "123456789",
- $this->getLang()->truncateForDatabase( "123456789", 5, 'XXXXXXXXXXXXXXX' ),
- 'truncate prefix, large ellipsis'
- );
- $this->assertEquals(
- "XXX67890",
- $this->getLang()->truncateForDatabase( "1234567890", -8, 'XXX' ),
- 'truncate suffix, small ellipsis'
- );
- $this->assertEquals(
- "123456789",
- $this->getLang()->truncateForDatabase( "123456789", -5, 'XXXXXXXXXXXXXXX' ),
- 'truncate suffix, large ellipsis'
- );
- $this->assertEquals(
- "123XXX",
- $this->getLang()->truncateForDatabase( "123 ", 9, 'XXX' ),
- 'truncate prefix, with spaces'
- );
- $this->assertEquals(
- "12345XXX",
- $this->getLang()->truncateForDatabase( "12345 8", 11, 'XXX' ),
- 'truncate prefix, with spaces and non-space ending'
- );
- $this->assertEquals(
- "XXX234",
- $this->getLang()->truncateForDatabase( "1 234", -8, 'XXX' ),
- 'truncate suffix, with spaces'
- );
- $this->assertEquals(
- "12345XXX",
- $this->getLang()->truncateForDatabase( "1234567890", 5, 'XXX', false ),
- 'truncate without adjustment'
- );
- $this->assertEquals(
- "泰乐菌...",
- $this->getLang()->truncateForDatabase( "泰乐菌素123456789", 11, '...', false ),
- 'truncate does not chop Unicode characters in half'
- );
- $this->assertEquals(
- "\n泰乐菌...",
- $this->getLang()->truncateForDatabase( "\n泰乐菌素123456789", 12, '...', false ),
- 'truncate does not chop Unicode characters in half if there is a preceding newline'
- );
- }
- /**
- * @dataProvider provideTruncateData
- * @covers Language::truncateForVisual
- * @covers Language::truncateInternal
- */
- public function testTruncateForVisual(
- $expected, $string, $length, $ellipsis = '...', $adjustLength = true
- ) {
- $this->assertEquals(
- $expected,
- $this->getLang()->truncateForVisual( $string, $length, $ellipsis, $adjustLength )
- );
- }
- /**
- * @return array Format is ($expected, $string, $length, $ellipsis, $adjustLength)
- */
- public static function provideTruncateData() {
- return [
- [ "XXX", "тестирам да ли ради", 0, "XXX" ],
- [ "testnXXX", "testni scenarij", 8, "XXX" ],
- [ "حالة اختبار", "حالة اختبار", 5, "XXXXXXXXXXXXXXX" ],
- [ "XXXедент", "прецедент", -8, "XXX" ],
- [ "XXപിൾ", "ആപ്പിൾ", -5, "XX" ],
- [ "神秘XXX", "神秘 ", 9, "XXX" ],
- [ "ΔημιουργXXX", "Δημιουργία Σύμπαντος", 11, "XXX" ],
- [ "XXXの家です", "地球は私たちの唯 の家です", -8, "XXX" ],
- [ "زندگیXXX", "زندگی زیباست", 6, "XXX", false ],
- [ "ცხოვრება...", "ცხოვრება არის საოცარი", 8, "...", false ],
- [ "\nທ່ານ...", "\nທ່ານບໍ່ຮູ້ຫນັງສື", 5, "...", false ],
- ];
- }
- /**
- * @dataProvider provideHTMLTruncateData
- * @covers Language::truncateHTML
- */
- public function testTruncateHtml( $len, $ellipsis, $input, $expected ) {
- // Actual HTML...
- $this->assertEquals(
- $expected,
- $this->getLang()->truncateHtml( $input, $len, $ellipsis )
- );
- }
- /**
- * @return array Format is ($len, $ellipsis, $input, $expected)
- */
- public static function provideHTMLTruncateData() {
- return [
- [ 0, 'XXX', "1234567890", "XXX" ],
- [ 8, 'XXX', "1234567890", "12345XXX" ],
- [ 5, 'XXXXXXXXXXXXXXX', '1234567890', "1234567890" ],
- [ 2, '***',
- '<p><span style="font-weight:bold;"></span></p>',
- '<p><span style="font-weight:bold;"></span></p>',
- ],
- [ 2, '***',
- '<p><span style="font-weight:bold;">123456789</span></p>',
- '<p><span style="font-weight:bold;">***</span></p>',
- ],
- [ 2, '***',
- '<p><span style="font-weight:bold;"> 23456789</span></p>',
- '<p><span style="font-weight:bold;">***</span></p>',
- ],
- [ 3, '***',
- '<p><span style="font-weight:bold;">123456789</span></p>',
- '<p><span style="font-weight:bold;">***</span></p>',
- ],
- [ 4, '***',
- '<p><span style="font-weight:bold;">123456789</span></p>',
- '<p><span style="font-weight:bold;">1***</span></p>',
- ],
- [ 5, '***',
- '<tt><span style="font-weight:bold;">123456789</span></tt>',
- '<tt><span style="font-weight:bold;">12***</span></tt>',
- ],
- [ 6, '***',
- '<p><a href="www.mediawiki.org">123456789</a></p>',
- '<p><a href="www.mediawiki.org">123***</a></p>',
- ],
- [ 6, '***',
- '<p><a href="www.mediawiki.org">12 456789</a></p>',
- '<p><a href="www.mediawiki.org">12 ***</a></p>',
- ],
- [ 7, '***',
- '<small><span style="font-weight:bold;">123<p id="#moo">456</p>789</span></small>',
- '<small><span style="font-weight:bold;">123<p id="#moo">4***</p></span></small>',
- ],
- [ 8, '***',
- '<div><span style="font-weight:bold;">123<span>4</span>56789</span></div>',
- '<div><span style="font-weight:bold;">123<span>4</span>5***</span></div>',
- ],
- [ 9, '***',
- '<p><table style="font-weight:bold;"><tr><td>123456789</td></tr></table></p>',
- '<p><table style="font-weight:bold;"><tr><td>123456789</td></tr></table></p>',
- ],
- [ 10, '***',
- '<p><font style="font-weight:bold;">123456789</font></p>',
- '<p><font style="font-weight:bold;">123456789</font></p>',
- ],
- ];
- }
- /**
- * Test Language::isWellFormedLanguageTag()
- * @dataProvider provideWellFormedLanguageTags
- * @covers Language::isWellFormedLanguageTag
- */
- public function testWellFormedLanguageTag( $code, $message = '' ) {
- $this->assertTrue(
- Language::isWellFormedLanguageTag( $code ),
- "validating code $code $message"
- );
- }
- /**
- * The test cases are based on the tests in the GaBuZoMeu parser
- * written by Stéphane Bortzmeyer <bortzmeyer@nic.fr>
- * and distributed as free software, under the GNU General Public Licence.
- * http://www.bortzmeyer.org/gabuzomeu-parsing-language-tags.html
- */
- public static function provideWellFormedLanguageTags() {
- return [
- [ 'fr', 'two-letter code' ],
- [ 'fr-latn', 'two-letter code with lower case script code' ],
- [ 'fr-Latn-FR', 'two-letter code with title case script code and uppercase country code' ],
- [ 'fr-Latn-419', 'two-letter code with title case script code and region number' ],
- [ 'fr-FR', 'two-letter code with uppercase' ],
- [ 'ax-TZ', 'Not in the registry, but well-formed' ],
- [ 'fr-shadok', 'two-letter code with variant' ],
- [ 'fr-y-myext-myext2', 'non-x singleton' ],
- [ 'fra-Latn', 'ISO 639 can be 3-letters' ],
- [ 'fra', 'three-letter language code' ],
- [ 'fra-FX', 'three-letter language code with country code' ],
- [ 'i-klingon', 'grandfathered with singleton' ],
- [ 'I-kLINgon', 'tags are case-insensitive...' ],
- [ 'no-bok', 'grandfathered without singleton' ],
- [ 'i-enochian', 'Grandfathered' ],
- [ 'x-fr-CH', 'private use' ],
- [ 'es-419', 'two-letter code with region number' ],
- [ 'en-Latn-GB-boont-r-extended-sequence-x-private', 'weird, but well-formed' ],
- [ 'ab-x-abc-x-abc', 'anything goes after x' ],
- [ 'ab-x-abc-a-a', 'anything goes after x, including several non-x singletons' ],
- [ 'i-default', 'grandfathered' ],
- [ 'abcd-Latn', 'Language of 4 chars reserved for future use' ],
- [ 'AaBbCcDd-x-y-any-x', 'Language of 5-8 chars, registered' ],
- [ 'de-CH-1901', 'with country and year' ],
- [ 'en-US-x-twain', 'with country and singleton' ],
- [ 'zh-cmn', 'three-letter variant' ],
- [ 'zh-cmn-Hant', 'three-letter variant and script' ],
- [ 'zh-cmn-Hant-HK', 'three-letter variant, script and country' ],
- [ 'xr-p-lze', 'Extension' ],
- ];
- }
- /**
- * Negative test for Language::isWellFormedLanguageTag()
- * @dataProvider provideMalformedLanguageTags
- * @covers Language::isWellFormedLanguageTag
- */
- public function testMalformedLanguageTag( $code, $message = '' ) {
- $this->assertFalse(
- Language::isWellFormedLanguageTag( $code ),
- "validating that code $code is a malformed language tag - $message"
- );
- }
- /**
- * The test cases are based on the tests in the GaBuZoMeu parser
- * written by Stéphane Bortzmeyer <bortzmeyer@nic.fr>
- * and distributed as free software, under the GNU General Public Licence.
- * http://www.bortzmeyer.org/gabuzomeu-parsing-language-tags.html
- */
- public static function provideMalformedLanguageTags() {
- return [
- [ 'f', 'language too short' ],
- [ 'f-Latn', 'language too short with script' ],
- [ 'xr-lxs-qut', 'variants too short' ], # extlangS
- [ 'fr-Latn-F', 'region too short' ],
- [ 'a-value', 'language too short with region' ],
- [ 'tlh-a-b-foo', 'valid three-letter with wrong variant' ],
- [
- 'i-notexist',
- 'grandfathered but not registered: invalid, even if we only test well-formedness'
- ],
- [ 'abcdefghi-012345678', 'numbers too long' ],
- [ 'ab-abc-abc-abc-abc', 'invalid extensions' ],
- [ 'ab-abcd-abc', 'invalid extensions' ],
- [ 'ab-ab-abc', 'invalid extensions' ],
- [ 'ab-123-abc', 'invalid extensions' ],
- [ 'a-Hant-ZH', 'short language with valid extensions' ],
- [ 'a1-Hant-ZH', 'invalid character in language' ],
- [ 'ab-abcde-abc', 'invalid extensions' ],
- [ 'ab-1abc-abc', 'invalid characters in extensions' ],
- [ 'ab-ab-abcd', 'invalid order of extensions' ],
- [ 'ab-123-abcd', 'invalid order of extensions' ],
- [ 'ab-abcde-abcd', 'invalid extensions' ],
- [ 'ab-1abc-abcd', 'invalid characters in extensions' ],
- [ 'ab-a-b', 'extensions too short' ],
- [ 'ab-a-x', 'extensions too short, even with singleton' ],
- [ 'ab--ab', 'two separators' ],
- [ 'ab-abc-', 'separator in the end' ],
- [ '-ab-abc', 'separator in the beginning' ],
- [ 'abcd-efg', 'language too long' ],
- [ 'aabbccddE', 'tag too long' ],
- [ 'pa_guru', 'A tag with underscore is invalid in strict mode' ],
- [ 'de-f', 'subtag too short' ],
- ];
- }
- /**
- * Negative test for Language::isWellFormedLanguageTag()
- * @covers Language::isWellFormedLanguageTag
- */
- public function testLenientLanguageTag() {
- $this->assertTrue(
- Language::isWellFormedLanguageTag( 'pa_guru', true ),
- 'pa_guru is a well-formed language tag in lenient mode'
- );
- }
- /**
- * Test Language::isValidBuiltInCode()
- * @dataProvider provideLanguageCodes
- * @covers Language::isValidBuiltInCode
- */
- public function testBuiltInCodeValidation( $code, $expected, $message = '' ) {
- $this->assertEquals( $expected,
- (bool)Language::isValidBuiltInCode( $code ),
- "validating code $code $message"
- );
- }
- public static function provideLanguageCodes() {
- return [
- [ 'fr', true, 'Two letters, minor case' ],
- [ 'EN', false, 'Two letters, upper case' ],
- [ 'tyv', true, 'Three letters' ],
- [ 'be-tarask', true, 'With dash' ],
- [ 'be-x-old', true, 'With extension (two dashes)' ],
- [ 'be_tarask', false, 'Reject underscores' ],
- ];
- }
- /**
- * Test Language::isKnownLanguageTag()
- * @dataProvider provideKnownLanguageTags
- * @covers Language::isKnownLanguageTag
- */
- public function testKnownLanguageTag( $code, $message = '' ) {
- $this->assertTrue(
- (bool)Language::isKnownLanguageTag( $code ),
- "validating code $code - $message"
- );
- }
- public static function provideKnownLanguageTags() {
- return [
- [ 'fr', 'simple code' ],
- [ 'bat-smg', 'an MW legacy tag' ],
- [ 'sgs', 'an internal standard MW name, for which a legacy tag is used externally' ],
- ];
- }
- /**
- * @covers Language::isKnownLanguageTag
- */
- public function testKnownCldrLanguageTag() {
- if ( !class_exists( 'LanguageNames' ) ) {
- $this->markTestSkipped( 'The LanguageNames class is not available. '
- . 'The CLDR extension is probably not installed.' );
- }
- $this->assertTrue(
- (bool)Language::isKnownLanguageTag( 'pal' ),
- 'validating code "pal" an ancient language, which probably will '
- . 'not appear in Names.php, but appears in CLDR in English'
- );
- }
- /**
- * Negative tests for Language::isKnownLanguageTag()
- * @dataProvider provideUnKnownLanguageTags
- * @covers Language::isKnownLanguageTag
- */
- public function testUnknownLanguageTag( $code, $message = '' ) {
- $this->assertFalse(
- (bool)Language::isKnownLanguageTag( $code ),
- "checking that code $code is invalid - $message"
- );
- }
- public static function provideUnknownLanguageTags() {
- return [
- [ 'mw', 'non-existent two-letter code' ],
- [ 'foo"<bar', 'very invalid language code' ],
- ];
- }
- /**
- * Test too short timestamp
- * @expectedException MWException
- * @covers Language::sprintfDate
- */
- public function testSprintfDateTooShortTimestamp() {
- $this->getLang()->sprintfDate( 'xiY', '1234567890123' );
- }
- /**
- * Test too long timestamp
- * @expectedException MWException
- * @covers Language::sprintfDate
- */
- public function testSprintfDateTooLongTimestamp() {
- $this->getLang()->sprintfDate( 'xiY', '123456789012345' );
- }
- /**
- * Test too short timestamp
- * @expectedException MWException
- * @covers Language::sprintfDate
- */
- public function testSprintfDateNotAllDigitTimestamp() {
- $this->getLang()->sprintfDate( 'xiY', '-1234567890123' );
- }
- /**
- * @dataProvider provideSprintfDateSamples
- * @covers Language::sprintfDate
- */
- public function testSprintfDate( $format, $ts, $expected, $msg ) {
- $ttl = null;
- $this->assertEquals(
- $expected,
- $this->getLang()->sprintfDate( $format, $ts, null, $ttl ),
- "sprintfDate('$format', '$ts'): $msg"
- );
- if ( $ttl ) {
- $dt = new DateTime( $ts );
- $lastValidTS = $dt->add( new DateInterval( 'PT' . ( $ttl - 1 ) . 'S' ) )->format( 'YmdHis' );
- $this->assertEquals(
- $expected,
- $this->getLang()->sprintfDate( $format, $lastValidTS, null ),
- "sprintfDate('$format', '$ts'): TTL $ttl too high (output was different at $lastValidTS)"
- );
- } else {
- // advance the time enough to make all of the possible outputs different (except possibly L)
- $dt = new DateTime( $ts );
- $newTS = $dt->add( new DateInterval( 'P1Y1M8DT13H1M1S' ) )->format( 'YmdHis' );
- $this->assertEquals(
- $expected,
- $this->getLang()->sprintfDate( $format, $newTS, null ),
- "sprintfDate('$format', '$ts'): Missing TTL (output was different at $newTS)"
- );
- }
- }
- /**
- * sprintfDate should always use UTC when no zone is given.
- * @dataProvider provideSprintfDateSamples
- * @covers Language::sprintfDate
- */
- public function testSprintfDateNoZone( $format, $ts, $expected, $ignore, $msg ) {
- $oldTZ = date_default_timezone_get();
- $res = date_default_timezone_set( 'Asia/Seoul' );
- if ( !$res ) {
- $this->markTestSkipped( "Error setting Timezone" );
- }
- $this->assertEquals(
- $expected,
- $this->getLang()->sprintfDate( $format, $ts ),
- "sprintfDate('$format', '$ts'): $msg"
- );
- date_default_timezone_set( $oldTZ );
- }
- /**
- * sprintfDate should use passed timezone
- * @dataProvider provideSprintfDateSamples
- * @covers Language::sprintfDate
- */
- public function testSprintfDateTZ( $format, $ts, $ignore, $expected, $msg ) {
- $tz = new DateTimeZone( 'Asia/Seoul' );
- if ( !$tz ) {
- $this->markTestSkipped( "Error getting Timezone" );
- }
- $this->assertEquals(
- $expected,
- $this->getLang()->sprintfDate( $format, $ts, $tz ),
- "sprintfDate('$format', '$ts', 'Asia/Seoul'): $msg"
- );
- }
- /**
- * sprintfDate should only calculate a TTL if the caller is going to use it.
- * @covers Language::sprintfDate
- */
- public function testSprintfDateNoTtlIfNotNeeded() {
- $noTtl = 'unused'; // Value used to represent that the caller didn't pass a variable in.
- $ttl = null;
- $this->getLang()->sprintfDate( 'YmdHis', wfTimestampNow(), null, $noTtl );
- $this->getLang()->sprintfDate( 'YmdHis', wfTimestampNow(), null, $ttl );
- $this->assertSame(
- 'unused',
- $noTtl,
- 'If the caller does not set the $ttl variable, do not compute it.'
- );
- $this->assertInternalType( 'int', $ttl, 'TTL should have been computed.' );
- }
- public static function provideSprintfDateSamples() {
- return [
- [
- 'xiY',
- '20111212000000',
- '1390', // note because we're testing English locale we get Latin-standard digits
- '1390',
- 'Iranian calendar full year'
- ],
- [
- 'xiy',
- '20111212000000',
- '90',
- '90',
- 'Iranian calendar short year'
- ],
- [
- 'o',
- '20120101235000',
- '2011',
- '2011',
- 'ISO 8601 (week) year'
- ],
- [
- 'W',
- '20120101235000',
- '52',
- '52',
- 'Week number'
- ],
- [
- 'W',
- '20120102235000',
- '1',
- '1',
- 'Week number'
- ],
- [
- 'o-\\WW-N',
- '20091231235000',
- '2009-W53-4',
- '2009-W53-4',
- 'leap week'
- ],
- // What follows is mostly copied from
- // https://www.mediawiki.org/wiki/Help:Extension:ParserFunctions#.23time
- [
- 'Y',
- '20120102090705',
- '2012',
- '2012',
- 'Full year'
- ],
- [
- 'y',
- '20120102090705',
- '12',
- '12',
- '2 digit year'
- ],
- [
- 'L',
- '20120102090705',
- '1',
- '1',
- 'Leap year'
- ],
- [
- 'n',
- '20120102090705',
- '1',
- '1',
- 'Month index, not zero pad'
- ],
- [
- 'N',
- '20120102090705',
- '01',
- '01',
- 'Month index. Zero pad'
- ],
- [
- 'M',
- '20120102090705',
- 'Jan',
- 'Jan',
- 'Month abbrev'
- ],
- [
- 'F',
- '20120102090705',
- 'January',
- 'January',
- 'Full month'
- ],
- [
- 'xg',
- '20120102090705',
- 'January',
- 'January',
- 'Genitive month name (same in EN)'
- ],
- [
- 'j',
- '20120102090705',
- '2',
- '2',
- 'Day of month (not zero pad)'
- ],
- [
- 'd',
- '20120102090705',
- '02',
- '02',
- 'Day of month (zero-pad)'
- ],
- [
- 'z',
- '20120102090705',
- '1',
- '1',
- 'Day of year (zero-indexed)'
- ],
- [
- 'D',
- '20120102090705',
- 'Mon',
- 'Mon',
- 'Day of week (abbrev)'
- ],
- [
- 'l',
- '20120102090705',
- 'Monday',
- 'Monday',
- 'Full day of week'
- ],
- [
- 'N',
- '20120101090705',
- '7',
- '7',
- 'Day of week (Mon=1, Sun=7)'
- ],
- [
- 'w',
- '20120101090705',
- '0',
- '0',
- 'Day of week (Sun=0, Sat=6)'
- ],
- [
- 'N',
- '20120102090705',
- '1',
- '1',
- 'Day of week'
- ],
- [
- 'a',
- '20120102090705',
- 'am',
- 'am',
- 'am vs pm'
- ],
- [
- 'A',
- '20120102120000',
- 'PM',
- 'PM',
- 'AM vs PM'
- ],
- [
- 'a',
- '20120102000000',
- 'am',
- 'am',
- 'AM vs PM'
- ],
- [
- 'g',
- '20120102090705',
- '9',
- '9',
- '12 hour, not Zero'
- ],
- [
- 'h',
- '20120102090705',
- '09',
- '09',
- '12 hour, zero padded'
- ],
- [
- 'G',
- '20120102090705',
- '9',
- '9',
- '24 hour, not zero'
- ],
- [
- 'H',
- '20120102090705',
- '09',
- '09',
- '24 hour, zero'
- ],
- [
- 'H',
- '20120102110705',
- '11',
- '11',
- '24 hour, zero'
- ],
- [
- 'i',
- '20120102090705',
- '07',
- '07',
- 'Minutes'
- ],
- [
- 's',
- '20120102090705',
- '05',
- '05',
- 'seconds'
- ],
- [
- 'U',
- '20120102090705',
- '1325495225',
- '1325462825',
- 'unix time'
- ],
- [
- 't',
- '20120102090705',
- '31',
- '31',
- 'Days in current month'
- ],
- [
- 'c',
- '20120102090705',
- '2012-01-02T09:07:05+00:00',
- '2012-01-02T09:07:05+09:00',
- 'ISO 8601 timestamp'
- ],
- [
- 'r',
- '20120102090705',
- 'Mon, 02 Jan 2012 09:07:05 +0000',
- 'Mon, 02 Jan 2012 09:07:05 +0900',
- 'RFC 5322'
- ],
- [
- 'e',
- '20120102090705',
- 'UTC',
- 'Asia/Seoul',
- 'Timezone identifier'
- ],
- [
- 'I',
- '19880602090705',
- '0',
- '1',
- 'DST indicator'
- ],
- [
- 'O',
- '20120102090705',
- '+0000',
- '+0900',
- 'Timezone offset'
- ],
- [
- 'P',
- '20120102090705',
- '+00:00',
- '+09:00',
- 'Timezone offset with colon'
- ],
- [
- 'T',
- '20120102090705',
- 'UTC',
- 'KST',
- 'Timezone abbreviation'
- ],
- [
- 'Z',
- '20120102090705',
- '0',
- '32400',
- 'Timezone offset in seconds'
- ],
- [
- 'xmj xmF xmn xmY',
- '20120102090705',
- '7 Safar 2 1433',
- '7 Safar 2 1433',
- 'Islamic'
- ],
- [
- 'xij xiF xin xiY',
- '20120102090705',
- '12 Dey 10 1390',
- '12 Dey 10 1390',
- 'Iranian'
- ],
- [
- 'xjj xjF xjn xjY',
- '20120102090705',
- '7 Tevet 4 5772',
- '7 Tevet 4 5772',
- 'Hebrew'
- ],
- [
- 'xjt',
- '20120102090705',
- '29',
- '29',
- 'Hebrew number of days in month'
- ],
- [
- 'xjx',
- '20120102090705',
- 'Tevet',
- 'Tevet',
- 'Hebrew genitive month name (No difference in EN)'
- ],
- [
- 'xkY',
- '20120102090705',
- '2555',
- '2555',
- 'Thai year'
- ],
- [
- 'xkY',
- '19410101090705',
- '2484',
- '2484',
- 'Thai year'
- ],
- [
- 'xoY',
- '20120102090705',
- '101',
- '101',
- 'Minguo'
- ],
- [
- 'xtY',
- '20120102090705',
- '平成24',
- '平成24',
- 'nengo'
- ],
- [
- 'xrxkYY',
- '20120102090705',
- 'MMDLV2012',
- 'MMDLV2012',
- 'Roman numerals'
- ],
- [
- 'xhxjYY',
- '20120102090705',
- 'ה\'תשע"ב2012',
- 'ה\'תשע"ב2012',
- 'Hebrew numberals'
- ],
- [
- 'xnY',
- '20120102090705',
- '2012',
- '2012',
- 'Raw numerals (doesn\'t mean much in EN)'
- ],
- [
- '[[Y "(yea"\\r)]] \\"xx\\"',
- '20120102090705',
- '[[2012 (year)]] "x"',
- '[[2012 (year)]] "x"',
- 'Various escaping'
- ],
- ];
- }
- /**
- * @dataProvider provideFormatSizes
- * @covers Language::formatSize
- */
- public function testFormatSize( $size, $expected, $msg ) {
- $this->assertEquals(
- $expected,
- $this->getLang()->formatSize( $size ),
- "formatSize('$size'): $msg"
- );
- }
- public static function provideFormatSizes() {
- return [
- [
- 0,
- "0 bytes",
- "Zero bytes"
- ],
- [
- 1024,
- "1 KB",
- "1 kilobyte"
- ],
- [
- 1024 * 1024,
- "1 MB",
- "1,024 megabytes"
- ],
- [
- 1024 * 1024 * 1024,
- "1 GB",
- "1 gigabyte"
- ],
- [
- 1024 ** 4,
- "1 TB",
- "1 terabyte"
- ],
- [
- 1024 ** 5,
- "1 PB",
- "1 petabyte"
- ],
- [
- 1024 ** 6,
- "1 EB",
- "1,024 exabyte"
- ],
- [
- 1024 ** 7,
- "1 ZB",
- "1 zetabyte"
- ],
- [
- 1024 ** 8,
- "1 YB",
- "1 yottabyte"
- ],
- // How big!? THIS BIG!
- ];
- }
- /**
- * @dataProvider provideFormatBitrate
- * @covers Language::formatBitrate
- */
- public function testFormatBitrate( $bps, $expected, $msg ) {
- $this->assertEquals(
- $expected,
- $this->getLang()->formatBitrate( $bps ),
- "formatBitrate('$bps'): $msg"
- );
- }
- public static function provideFormatBitrate() {
- return [
- [
- 0,
- "0 bps",
- "0 bits per second"
- ],
- [
- 999,
- "999 bps",
- "999 bits per second"
- ],
- [
- 1000,
- "1 kbps",
- "1 kilobit per second"
- ],
- [
- 1000 * 1000,
- "1 Mbps",
- "1 megabit per second"
- ],
- [
- 10 ** 9,
- "1 Gbps",
- "1 gigabit per second"
- ],
- [
- 10 ** 12,
- "1 Tbps",
- "1 terabit per second"
- ],
- [
- 10 ** 15,
- "1 Pbps",
- "1 petabit per second"
- ],
- [
- 10 ** 18,
- "1 Ebps",
- "1 exabit per second"
- ],
- [
- 10 ** 21,
- "1 Zbps",
- "1 zetabit per second"
- ],
- [
- 10 ** 24,
- "1 Ybps",
- "1 yottabit per second"
- ],
- [
- 10 ** 27,
- "1,000 Ybps",
- "1,000 yottabits per second"
- ],
- ];
- }
- /**
- * @dataProvider provideFormatDuration
- * @covers Language::formatDuration
- */
- public function testFormatDuration( $duration, $expected, $intervals = [] ) {
- $this->assertEquals(
- $expected,
- $this->getLang()->formatDuration( $duration, $intervals ),
- "formatDuration('$duration'): $expected"
- );
- }
- public static function provideFormatDuration() {
- return [
- [
- 0,
- '0 seconds',
- ],
- [
- 1,
- '1 second',
- ],
- [
- 2,
- '2 seconds',
- ],
- [
- 60,
- '1 minute',
- ],
- [
- 2 * 60,
- '2 minutes',
- ],
- [
- 3600,
- '1 hour',
- ],
- [
- 2 * 3600,
- '2 hours',
- ],
- [
- 24 * 3600,
- '1 day',
- ],
- [
- 2 * 86400,
- '2 days',
- ],
- [
- // ( 365 + ( 24 * 3 + 25 ) / 400 ) * 86400 = 31556952
- ( 365 + ( 24 * 3 + 25 ) / 400.0 ) * 86400,
- '1 year',
- ],
- [
- 2 * 31556952,
- '2 years',
- ],
- [
- 10 * 31556952,
- '1 decade',
- ],
- [
- 20 * 31556952,
- '2 decades',
- ],
- [
- 100 * 31556952,
- '1 century',
- ],
- [
- 200 * 31556952,
- '2 centuries',
- ],
- [
- 1000 * 31556952,
- '1 millennium',
- ],
- [
- 2000 * 31556952,
- '2 millennia',
- ],
- [
- 9001,
- '2 hours, 30 minutes and 1 second'
- ],
- [
- 3601,
- '1 hour and 1 second'
- ],
- [
- 31556952 + 2 * 86400 + 9000,
- '1 year, 2 days, 2 hours and 30 minutes'
- ],
- [
- 42 * 1000 * 31556952 + 42,
- '42 millennia and 42 seconds'
- ],
- [
- 60,
- '60 seconds',
- [ 'seconds' ],
- ],
- [
- 61,
- '61 seconds',
- [ 'seconds' ],
- ],
- [
- 1,
- '1 second',
- [ 'seconds' ],
- ],
- [
- 31556952 + 2 * 86400 + 9000,
- '1 year, 2 days and 150 minutes',
- [ 'years', 'days', 'minutes' ],
- ],
- [
- 42,
- '0 days',
- [ 'years', 'days' ],
- ],
- [
- 31556952 + 2 * 86400 + 9000,
- '1 year, 2 days and 150 minutes',
- [ 'minutes', 'days', 'years' ],
- ],
- [
- 42,
- '0 days',
- [ 'days', 'years' ],
- ],
- ];
- }
- /**
- * @dataProvider provideCheckTitleEncodingData
- * @covers Language::checkTitleEncoding
- */
- public function testCheckTitleEncoding( $s ) {
- $this->assertEquals(
- $s,
- $this->getLang()->checkTitleEncoding( $s ),
- "checkTitleEncoding('$s')"
- );
- }
- public static function provideCheckTitleEncodingData() {
- // phpcs:disable Generic.Files.LineLength
- return [
- [ "" ],
- [ "United States of America" ], // 7bit ASCII
- [ rawurldecode( "S%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e" ) ],
- [
- rawurldecode(
- "Acteur%7CAlbert%20Robbins%7CAnglais%7CAnn%20Donahue%7CAnthony%20E.%20Zuiker%7CCarol%20Mendelsohn"
- )
- ],
- // The following two data sets come from T38839. They fail if checkTitleEncoding uses a regexp to test for
- // valid UTF-8 encoding and the pcre.recursion_limit is low (like, say, 1024). They succeed if checkTitleEncoding
- // uses mb_check_encoding for its test.
- [
- rawurldecode(
- "Acteur%7CAlbert%20Robbins%7CAnglais%7CAnn%20Donahue%7CAnthony%20E.%20Zuiker%7CCarol%20Mendelsohn%7C"
- . "Catherine%20Willows%7CDavid%20Hodges%7CDavid%20Phillips%7CGil%20Grissom%7CGreg%20Sanders%7CHodges%7C"
- . "Internet%20Movie%20Database%7CJim%20Brass%7CLady%20Heather%7C"
- . "Les%20Experts%20(s%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e)%7CLes%20Experts%20:%20Manhattan%7C"
- . "Les%20Experts%20:%20Miami%7CListe%20des%20personnages%20des%20Experts%7C"
- . "Liste%20des%20%C3%A9pisodes%20des%20Experts%7CMod%C3%A8le%20discussion:Palette%20Les%20Experts%7C"
- . "Nick%20Stokes%7CPersonnage%20de%20fiction%7CPersonnage%20fictif%7CPersonnage%20de%20fiction%7C"
- . "Personnages%20r%C3%A9currents%20dans%20Les%20Experts%7CRaymond%20Langston%7CRiley%20Adams%7C"
- . "Saison%201%20des%20Experts%7CSaison%2010%20des%20Experts%7CSaison%2011%20des%20Experts%7C"
- . "Saison%2012%20des%20Experts%7CSaison%202%20des%20Experts%7CSaison%203%20des%20Experts%7C"
- . "Saison%204%20des%20Experts%7CSaison%205%20des%20Experts%7CSaison%206%20des%20Experts%7C"
- . "Saison%207%20des%20Experts%7CSaison%208%20des%20Experts%7CSaison%209%20des%20Experts%7C"
- . "Sara%20Sidle%7CSofia%20Curtis%7CS%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e%7CWallace%20Langham%7C"
- . "Warrick%20Brown%7CWendy%20Simms%7C%C3%89tats-Unis"
- ),
- ],
- [
- rawurldecode(
- "Mod%C3%A8le%3AArrondissements%20homonymes%7CMod%C3%A8le%3ABandeau%20standard%20pour%20page%20d'homonymie%7C"
- . "Mod%C3%A8le%3ABatailles%20homonymes%7CMod%C3%A8le%3ACantons%20homonymes%7C"
- . "Mod%C3%A8le%3ACommunes%20fran%C3%A7aises%20homonymes%7CMod%C3%A8le%3AFilms%20homonymes%7C"
- . "Mod%C3%A8le%3AGouvernements%20homonymes%7CMod%C3%A8le%3AGuerres%20homonymes%7CMod%C3%A8le%3AHomonymie%7C"
- . "Mod%C3%A8le%3AHomonymie%20bateau%7CMod%C3%A8le%3AHomonymie%20d'%C3%A9tablissements%20scolaires%20ou"
- . "%20universitaires%7CMod%C3%A8le%3AHomonymie%20d'%C3%AEles%7CMod%C3%A8le%3AHomonymie%20de%20clubs%20sportifs%7C"
- . "Mod%C3%A8le%3AHomonymie%20de%20comt%C3%A9s%7CMod%C3%A8le%3AHomonymie%20de%20monument%7C"
- . "Mod%C3%A8le%3AHomonymie%20de%20nom%20romain%7CMod%C3%A8le%3AHomonymie%20de%20parti%20politique%7C"
- . "Mod%C3%A8le%3AHomonymie%20de%20route%7CMod%C3%A8le%3AHomonymie%20dynastique%7C"
- . "Mod%C3%A8le%3AHomonymie%20vid%C3%A9oludique%7CMod%C3%A8le%3AHomonymie%20%C3%A9difice%20religieux%7C"
- . "Mod%C3%A8le%3AInternationalisation%7CMod%C3%A8le%3AIsom%C3%A9rie%7CMod%C3%A8le%3AParonymie%7C"
- . "Mod%C3%A8le%3APatronyme%7CMod%C3%A8le%3APatronyme%20basque%7CMod%C3%A8le%3APatronyme%20italien%7C"
- . "Mod%C3%A8le%3APatronymie%7CMod%C3%A8le%3APersonnes%20homonymes%7CMod%C3%A8le%3ASaints%20homonymes%7C"
- . "Mod%C3%A8le%3ATitres%20homonymes%7CMod%C3%A8le%3AToponymie%7CMod%C3%A8le%3AUnit%C3%A9s%20homonymes%7C"
- . "Mod%C3%A8le%3AVilles%20homonymes%7CMod%C3%A8le%3A%C3%89difices%20religieux%20homonymes"
- )
- ]
- ];
- // phpcs:enable
- }
- /**
- * @dataProvider provideRomanNumeralsData
- * @covers Language::romanNumeral
- */
- public function testRomanNumerals( $num, $numerals ) {
- $this->assertEquals(
- $numerals,
- Language::romanNumeral( $num ),
- "romanNumeral('$num')"
- );
- }
- public static function provideRomanNumeralsData() {
- return [
- [ 1, 'I' ],
- [ 2, 'II' ],
- [ 3, 'III' ],
- [ 4, 'IV' ],
- [ 5, 'V' ],
- [ 6, 'VI' ],
- [ 7, 'VII' ],
- [ 8, 'VIII' ],
- [ 9, 'IX' ],
- [ 10, 'X' ],
- [ 20, 'XX' ],
- [ 30, 'XXX' ],
- [ 40, 'XL' ],
- [ 49, 'XLIX' ],
- [ 50, 'L' ],
- [ 60, 'LX' ],
- [ 70, 'LXX' ],
- [ 80, 'LXXX' ],
- [ 90, 'XC' ],
- [ 99, 'XCIX' ],
- [ 100, 'C' ],
- [ 200, 'CC' ],
- [ 300, 'CCC' ],
- [ 400, 'CD' ],
- [ 500, 'D' ],
- [ 600, 'DC' ],
- [ 700, 'DCC' ],
- [ 800, 'DCCC' ],
- [ 900, 'CM' ],
- [ 999, 'CMXCIX' ],
- [ 1000, 'M' ],
- [ 1989, 'MCMLXXXIX' ],
- [ 2000, 'MM' ],
- [ 3000, 'MMM' ],
- [ 4000, 'MMMM' ],
- [ 5000, 'MMMMM' ],
- [ 6000, 'MMMMMM' ],
- [ 7000, 'MMMMMMM' ],
- [ 8000, 'MMMMMMMM' ],
- [ 9000, 'MMMMMMMMM' ],
- [ 9999, 'MMMMMMMMMCMXCIX' ],
- [ 10000, 'MMMMMMMMMM' ],
- ];
- }
- /**
- * @dataProvider provideHebrewNumeralsData
- * @covers Language::hebrewNumeral
- */
- public function testHebrewNumeral( $num, $numerals ) {
- $this->assertEquals(
- $numerals,
- Language::hebrewNumeral( $num ),
- "hebrewNumeral('$num')"
- );
- }
- public static function provideHebrewNumeralsData() {
- return [
- [ -1, -1 ],
- [ 0, 0 ],
- [ 1, "א'" ],
- [ 2, "ב'" ],
- [ 3, "ג'" ],
- [ 4, "ד'" ],
- [ 5, "ה'" ],
- [ 6, "ו'" ],
- [ 7, "ז'" ],
- [ 8, "ח'" ],
- [ 9, "ט'" ],
- [ 10, "י'" ],
- [ 11, 'י"א' ],
- [ 14, 'י"ד' ],
- [ 15, 'ט"ו' ],
- [ 16, 'ט"ז' ],
- [ 17, 'י"ז' ],
- [ 20, "כ'" ],
- [ 21, 'כ"א' ],
- [ 30, "ל'" ],
- [ 40, "מ'" ],
- [ 50, "נ'" ],
- [ 60, "ס'" ],
- [ 70, "ע'" ],
- [ 80, "פ'" ],
- [ 90, "צ'" ],
- [ 99, 'צ"ט' ],
- [ 100, "ק'" ],
- [ 101, 'ק"א' ],
- [ 110, 'ק"י' ],
- [ 200, "ר'" ],
- [ 300, "ש'" ],
- [ 400, "ת'" ],
- [ 500, 'ת"ק' ],
- [ 800, 'ת"ת' ],
- [ 1000, "א' אלף" ],
- [ 1001, "א'א'" ],
- [ 1012, "א'י\"ב" ],
- [ 1020, "א'ך'" ],
- [ 1030, "א'ל'" ],
- [ 1081, "א'פ\"א" ],
- [ 2000, "ב' אלפים" ],
- [ 2016, "ב'ט\"ז" ],
- [ 3000, "ג' אלפים" ],
- [ 4000, "ד' אלפים" ],
- [ 4904, "ד'תתק\"ד" ],
- [ 5000, "ה' אלפים" ],
- [ 5680, "ה'תר\"ף" ],
- [ 5690, "ה'תר\"ץ" ],
- [ 5708, "ה'תש\"ח" ],
- [ 5720, "ה'תש\"ך" ],
- [ 5740, "ה'תש\"ם" ],
- [ 5750, "ה'תש\"ן" ],
- [ 5775, "ה'תשע\"ה" ],
- ];
- }
- /**
- * @dataProvider providePluralData
- * @covers Language::convertPlural
- */
- public function testConvertPlural( $expected, $number, $forms ) {
- $chosen = $this->getLang()->convertPlural( $number, $forms );
- $this->assertEquals( $expected, $chosen );
- }
- public static function providePluralData() {
- // Params are: [expected text, number given, [the plural forms]]
- return [
- [ 'plural', 0, [
- 'singular', 'plural'
- ] ],
- [ 'explicit zero', 0, [
- '0=explicit zero', 'singular', 'plural'
- ] ],
- [ 'explicit one', 1, [
- 'singular', 'plural', '1=explicit one',
- ] ],
- [ 'singular', 1, [
- 'singular', 'plural', '0=explicit zero',
- ] ],
- [ 'plural', 3, [
- '0=explicit zero', '1=explicit one', 'singular', 'plural'
- ] ],
- [ 'explicit eleven', 11, [
- 'singular', 'plural', '11=explicit eleven',
- ] ],
- [ 'plural', 12, [
- 'singular', 'plural', '11=explicit twelve',
- ] ],
- [ 'plural', 12, [
- 'singular', 'plural', '=explicit form',
- ] ],
- [ 'other', 2, [
- 'kissa=kala', '1=2=3', 'other',
- ] ],
- [ '', 2, [
- '0=explicit zero', '1=explicit one',
- ] ],
- ];
- }
- /**
- * @covers Language::embedBidi()
- */
- public function testEmbedBidi() {
- $lre = "\u{202A}"; // U+202A LEFT-TO-RIGHT EMBEDDING
- $rle = "\u{202B}"; // U+202B RIGHT-TO-LEFT EMBEDDING
- $pdf = "\u{202C}"; // U+202C POP DIRECTIONAL FORMATTING
- $lang = $this->getLang();
- $this->assertEquals(
- '123',
- $lang->embedBidi( '123' ),
- 'embedBidi with neutral argument'
- );
- $this->assertEquals(
- $lre . 'Ben_(WMF)' . $pdf,
- $lang->embedBidi( 'Ben_(WMF)' ),
- 'embedBidi with LTR argument'
- );
- $this->assertEquals(
- $rle . 'יהודי (מנוחין)' . $pdf,
- $lang->embedBidi( 'יהודי (מנוחין)' ),
- 'embedBidi with RTL argument'
- );
- }
- /**
- * @covers Language::translateBlockExpiry()
- * @dataProvider provideTranslateBlockExpiry
- */
- public function testTranslateBlockExpiry( $expectedData, $str, $now, $desc ) {
- $lang = $this->getLang();
- if ( is_array( $expectedData ) ) {
- list( $func, $arg ) = $expectedData;
- $expected = $lang->$func( $arg );
- } else {
- $expected = $expectedData;
- }
- $this->assertEquals( $expected, $lang->translateBlockExpiry( $str, null, $now ), $desc );
- }
- public static function provideTranslateBlockExpiry() {
- return [
- [ '2 hours', '2 hours', 0, 'simple data from ipboptions' ],
- [ 'indefinite', 'infinite', 0, 'infinite from ipboptions' ],
- [ 'indefinite', 'infinity', 0, 'alternative infinite from ipboptions' ],
- [ 'indefinite', 'indefinite', 0, 'another alternative infinite from ipboptions' ],
- [ [ 'formatDuration', 1023 * 60 * 60 ], '1023 hours', 0, 'relative' ],
- [ [ 'formatDuration', -1023 ], '-1023 seconds', 0, 'negative relative' ],
- [
- [ 'formatDuration', 1023 * 60 * 60 ],
- '1023 hours',
- wfTimestamp( TS_UNIX, '19910203040506' ),
- 'relative with initial timestamp'
- ],
- [ [ 'formatDuration', 0 ], 'now', 0, 'now' ],
- [
- [ 'timeanddate', '20120102070000' ],
- '2012-1-1 7:00 +1 day',
- 0,
- 'mixed, handled as absolute'
- ],
- [ [ 'timeanddate', '19910203040506' ], '1991-2-3 4:05:06', 0, 'absolute' ],
- [ [ 'timeanddate', '19700101000000' ], '1970-1-1 0:00:00', 0, 'absolute at epoch' ],
- [ [ 'timeanddate', '19691231235959' ], '1969-12-31 23:59:59', 0, 'time before epoch' ],
- [
- [ 'timeanddate', '19910910000000' ],
- '10 september',
- wfTimestamp( TS_UNIX, '19910203040506' ),
- 'partial'
- ],
- [ 'dummy', 'dummy', 0, 'return garbage as is' ],
- ];
- }
- /**
- * @dataProvider provideFormatNum
- * @covers Language::formatNum
- */
- public function testFormatNum(
- $translateNumerals, $langCode, $number, $nocommafy, $expected
- ) {
- $this->setMwGlobals( [ 'wgTranslateNumerals' => $translateNumerals ] );
- $lang = Language::factory( $langCode );
- $formattedNum = $lang->formatNum( $number, $nocommafy );
- $this->assertType( 'string', $formattedNum );
- $this->assertEquals( $expected, $formattedNum );
- }
- public function provideFormatNum() {
- return [
- [ true, 'en', 100, false, '100' ],
- [ true, 'en', 101, true, '101' ],
- [ false, 'en', 103, false, '103' ],
- [ false, 'en', 104, true, '104' ],
- [ true, 'en', '105', false, '105' ],
- [ true, 'en', '106', true, '106' ],
- [ false, 'en', '107', false, '107' ],
- [ false, 'en', '108', true, '108' ],
- ];
- }
- /**
- * @covers Language::parseFormattedNumber
- * @dataProvider parseFormattedNumberProvider
- */
- public function testParseFormattedNumber( $langCode, $number ) {
- $lang = Language::factory( $langCode );
- $localisedNum = $lang->formatNum( $number );
- $normalisedNum = $lang->parseFormattedNumber( $localisedNum );
- $this->assertEquals( $number, $normalisedNum );
- }
- public function parseFormattedNumberProvider() {
- return [
- [ 'de', 377.01 ],
- [ 'fa', 334 ],
- [ 'fa', 382.772 ],
- [ 'ar', 1844 ],
- [ 'lzh', 3731 ],
- [ 'zh-classical', 7432 ]
- ];
- }
- /**
- * @covers Language::commafy()
- * @dataProvider provideCommafyData
- */
- public function testCommafy( $number, $numbersWithCommas ) {
- $this->assertEquals(
- $numbersWithCommas,
- $this->getLang()->commafy( $number ),
- "commafy('$number')"
- );
- }
- public static function provideCommafyData() {
- return [
- [ -1, '-1' ],
- [ 10, '10' ],
- [ 100, '100' ],
- [ 1000, '1,000' ],
- [ 10000, '10,000' ],
- [ 100000, '100,000' ],
- [ 1000000, '1,000,000' ],
- [ -1.0001, '-1.0001' ],
- [ 1.0001, '1.0001' ],
- [ 10.0001, '10.0001' ],
- [ 100.0001, '100.0001' ],
- [ 1000.0001, '1,000.0001' ],
- [ 10000.0001, '10,000.0001' ],
- [ 100000.0001, '100,000.0001' ],
- [ 1000000.0001, '1,000,000.0001' ],
- [ '200000000000000000000', '200,000,000,000,000,000,000' ],
- [ '-200000000000000000000', '-200,000,000,000,000,000,000' ],
- ];
- }
- /**
- * @covers Language::listToText
- */
- public function testListToText() {
- $lang = $this->getLang();
- $and = $lang->getMessageFromDB( 'and' );
- $s = $lang->getMessageFromDB( 'word-separator' );
- $c = $lang->getMessageFromDB( 'comma-separator' );
- $this->assertEquals( '', $lang->listToText( [] ) );
- $this->assertEquals( 'a', $lang->listToText( [ 'a' ] ) );
- $this->assertEquals( "a{$and}{$s}b", $lang->listToText( [ 'a', 'b' ] ) );
- $this->assertEquals( "a{$c}b{$and}{$s}c", $lang->listToText( [ 'a', 'b', 'c' ] ) );
- $this->assertEquals( "a{$c}b{$c}c{$and}{$s}d", $lang->listToText( [ 'a', 'b', 'c', 'd' ] ) );
- }
- /**
- * @covers Language::clearCaches
- */
- public function testClearCaches() {
- $languageClass = TestingAccessWrapper::newFromClass( Language::class );
- // Populate $dataCache
- Language::getLocalisationCache()->getItem( 'zh', 'mainpage' );
- $oldCacheObj = Language::$dataCache;
- $this->assertNotCount( 0,
- TestingAccessWrapper::newFromObject( Language::$dataCache )->loadedItems );
- // Populate $mLangObjCache
- $lang = Language::factory( 'en' );
- $this->assertNotCount( 0, Language::$mLangObjCache );
- // Populate $fallbackLanguageCache
- Language::getFallbacksIncludingSiteLanguage( 'en' );
- $this->assertNotCount( 0, $languageClass->fallbackLanguageCache );
- // Populate $grammarTransformations
- $lang->getGrammarTransformations();
- $this->assertNotNull( $languageClass->grammarTransformations );
- // Populate $languageNameCache
- Language::fetchLanguageNames();
- $this->assertNotNull( $languageClass->languageNameCache );
- Language::clearCaches();
- $this->assertNotSame( $oldCacheObj, Language::$dataCache );
- $this->assertCount( 0,
- TestingAccessWrapper::newFromObject( Language::$dataCache )->loadedItems );
- $this->assertCount( 0, Language::$mLangObjCache );
- $this->assertCount( 0, $languageClass->fallbackLanguageCache );
- $this->assertNull( $languageClass->grammarTransformations );
- $this->assertNull( $languageClass->languageNameCache );
- }
- /**
- * @dataProvider provideIsSupportedLanguage
- * @covers Language::isSupportedLanguage
- */
- public function testIsSupportedLanguage( $code, $expected, $comment ) {
- $this->assertEquals( $expected, Language::isSupportedLanguage( $code ), $comment );
- }
- public static function provideIsSupportedLanguage() {
- return [
- [ 'en', true, 'is supported language' ],
- [ 'fi', true, 'is supported language' ],
- [ 'bunny', false, 'is not supported language' ],
- [ 'FI', false, 'is not supported language, input should be in lower case' ],
- ];
- }
- /**
- * @dataProvider provideGetParentLanguage
- * @covers Language::getParentLanguage
- */
- public function testGetParentLanguage( $code, $expected, $comment ) {
- $lang = Language::factory( $code );
- if ( is_null( $expected ) ) {
- $this->assertNull( $lang->getParentLanguage(), $comment );
- } else {
- $this->assertEquals( $expected, $lang->getParentLanguage()->getCode(), $comment );
- }
- }
- public static function provideGetParentLanguage() {
- return [
- [ 'zh-cn', 'zh', 'zh is the parent language of zh-cn' ],
- [ 'zh', 'zh', 'zh is defined as the parent language of zh, '
- . 'because zh converter can convert zh-cn to zh' ],
- [ 'zh-invalid', null, 'do not be fooled by arbitrarily composed language codes' ],
- [ 'de-formal', null, 'de does not have converter' ],
- [ 'de', null, 'de does not have converter' ],
- ];
- }
- /**
- * @dataProvider provideGetNamespaceAliases
- * @covers Language::getNamespaceAliases
- */
- public function testGetNamespaceAliases( $languageCode, $subset ) {
- $language = Language::factory( $languageCode );
- $aliases = $language->getNamespaceAliases();
- foreach ( $subset as $alias => $nsId ) {
- $this->assertEquals( $nsId, $aliases[$alias] );
- }
- }
- public static function provideGetNamespaceAliases() {
- // TODO: Add tests for NS_PROJECT_TALK and GenderNamespaces
- return [
- [
- 'zh',
- [
- '文件' => NS_FILE,
- '檔案' => NS_FILE,
- ],
- ],
- ];
- }
- /**
- * @covers Language::equals
- */
- public function testEquals() {
- $en1 = new Language();
- $en1->setCode( 'en' );
- $en2 = Language::factory( 'en' );
- $en2->setCode( 'en' );
- $this->assertTrue( $en1->equals( $en2 ), 'en equals en' );
- $fr = Language::factory( 'fr' );
- $this->assertFalse( $en1->equals( $fr ), 'en not equals fr' );
- }
- }
|