Merge "Add attributes parameter to ShowSearchHitTitle"
[lhc/web/wiklou.git] / tests / qunit / suites / resources / mediawiki / mediawiki.language.test.js
1 ( function ( mw, $ ) {
2 'use strict';
3
4 var grammarTests, bcp47Tests;
5
6 QUnit.module( 'mediawiki.language', QUnit.newMwEnvironment( {
7 setup: function () {
8 this.liveLangData = mw.language.data;
9 mw.language.data = {};
10 },
11 teardown: function () {
12 mw.language.data = this.liveLangData;
13 },
14 messages: {
15 // mw.language.listToText test
16 and: ' and',
17 'comma-separator': ', ',
18 'word-separator': ' '
19 }
20 } ) );
21
22 QUnit.test( 'mw.language getData and setData', function ( assert ) {
23 mw.language.setData( 'en', 'testkey', 'testvalue' );
24 assert.equal( mw.language.getData( 'en', 'testkey' ), 'testvalue', 'Getter setter test for mw.language' );
25 assert.equal( mw.language.getData( 'en', 'invalidkey' ), undefined, 'Getter setter test for mw.language with invalid key' );
26 mw.language.setData( 'en-us', 'testkey', 'testvalue' );
27 assert.equal( mw.language.getData( 'en-US', 'testkey' ), 'testvalue', 'Case insensitive test for mw.language' );
28 } );
29
30 QUnit.test( 'mw.language.commafy test', function ( assert ) {
31 mw.language.setData( 'en', 'digitGroupingPattern', null );
32 mw.language.setData( 'en', 'digitTransformTable', null );
33 mw.language.setData( 'en', 'separatorTransformTable', null );
34
35 mw.config.set( 'wgUserLanguage', 'en' );
36 // Number grouping patterns are as per http://cldr.unicode.org/translation/number-patterns
37 assert.equal( mw.language.commafy( 1234.567, '###0.#####' ), '1234.567', 'Pattern with no digit grouping separator defined' );
38 assert.equal( mw.language.commafy( 123456789.567, '###0.#####' ), '123456789.567', 'Pattern with no digit grouping separator defined, bigger decimal part' );
39 assert.equal( mw.language.commafy( 0.567, '###0.#####' ), '0.567', 'Decimal part 0' );
40 assert.equal( mw.language.commafy( '.567', '###0.#####' ), '0.567', 'Decimal part missing. replace with zero' );
41 assert.equal( mw.language.commafy( 1234, '##,#0.#####' ), '12,34', 'Pattern with no fractional part' );
42 assert.equal( mw.language.commafy( -1234.567, '###0.#####' ), '-1234.567', 'Negative number' );
43 assert.equal( mw.language.commafy( -1234.567, '#,###.00' ), '-1,234.56', 'Fractional part bigger than pattern.' );
44 assert.equal( mw.language.commafy( 123456789.567, '###,##0.00' ), '123,456,789.56', 'Decimal part as group of 3' );
45 assert.equal( mw.language.commafy( 123456789.567, '###,###,#0.00' ), '1,234,567,89.56', 'Decimal part as group of 3 and last one 2' );
46 } );
47
48 QUnit.test( 'mw.language.convertNumber', function ( assert ) {
49 mw.language.setData( 'en', 'digitGroupingPattern', null );
50 mw.language.setData( 'en', 'digitTransformTable', null );
51 mw.language.setData( 'en', 'separatorTransformTable', { ',': '.', '.': ',' } );
52 mw.config.set( 'wgUserLanguage', 'en' );
53 mw.config.set( 'wgTranslateNumerals', true );
54
55 assert.equal( mw.language.convertNumber( 1800 ), '1.800', 'formatting' );
56 assert.equal( mw.language.convertNumber( '1.800', true ), '1800', 'unformatting' );
57 } );
58
59 QUnit.test( 'mw.language.convertNumber - digitTransformTable', function ( assert ) {
60 mw.config.set( 'wgUserLanguage', 'hi' );
61 mw.config.set( 'wgTranslateNumerals', true );
62 mw.language.setData( 'hi', 'digitGroupingPattern', null );
63 mw.language.setData( 'hi', 'separatorTransformTable', { ',': '.', '.': ',' } );
64
65 // Example from Hindi (MessagesHi.php)
66 mw.language.setData( 'hi', 'digitTransformTable', {
67 0: '०',
68 1: '१',
69 2: '२'
70 } );
71
72 assert.equal( mw.language.convertNumber( 1200 ), '१.२००', 'format' );
73 assert.equal( mw.language.convertNumber( '१.२००', true ), '1200', 'unformat from digit transform' );
74 assert.equal( mw.language.convertNumber( '1.200', true ), '1200', 'unformat plain' );
75
76 mw.config.set( 'wgTranslateNumerals', false );
77
78 assert.equal( mw.language.convertNumber( 1200 ), '1.200', 'format (digit transform disabled)' );
79 assert.equal( mw.language.convertNumber( '१.२००', true ), '1200', 'unformat from digit transform (when disabled)' );
80 assert.equal( mw.language.convertNumber( '1.200', true ), '1200', 'unformat plain (digit transform disabled)' );
81 } );
82
83 function grammarTest( langCode, test ) {
84 // The test works only if the content language is opt.language
85 // because it requires [lang].js to be loaded.
86 QUnit.test( 'Grammar test for lang=' + langCode, function ( assert ) {
87 var i;
88 for ( i = 0; i < test.length; i++ ) {
89 assert.equal(
90 mw.language.convertGrammar( test[ i ].word, test[ i ].grammarForm ),
91 test[ i ].expected,
92 test[ i ].description
93 );
94 }
95 } );
96 }
97
98 // These tests run only for the current UI language.
99 grammarTests = {
100 bs: [
101 {
102 word: 'word',
103 grammarForm: 'instrumental',
104 expected: 's word',
105 description: 'Grammar test for instrumental case'
106 },
107 {
108 word: 'word',
109 grammarForm: 'lokativ',
110 expected: 'o word',
111 description: 'Grammar test for lokativ case'
112 }
113 ],
114
115 he: [
116 {
117 word: 'ויקיפדיה',
118 grammarForm: 'prefixed',
119 expected: 'וויקיפדיה',
120 description: 'Duplicate the "Waw" if prefixed'
121 },
122 {
123 word: 'וולפגנג',
124 grammarForm: 'prefixed',
125 expected: 'וולפגנג',
126 description: 'Duplicate the "Waw" if prefixed, but not if it is already duplicated.'
127 },
128 {
129 word: 'הקובץ',
130 grammarForm: 'prefixed',
131 expected: 'קובץ',
132 description: 'Remove the "He" if prefixed'
133 },
134 {
135 word: 'Wikipedia',
136 grammarForm: 'תחילית',
137 expected: '־Wikipedia',
138 description: 'Add a hyphen (maqaf) before non-Hebrew letters'
139 },
140 {
141 word: '1995',
142 grammarForm: 'תחילית',
143 expected: '־1995',
144 description: 'Add a hyphen (maqaf) before numbers'
145 }
146 ],
147
148 hsb: [
149 {
150 word: 'word',
151 grammarForm: 'instrumental',
152 expected: 'z word',
153 description: 'Grammar test for instrumental case'
154 },
155 {
156 word: 'word',
157 grammarForm: 'lokatiw',
158 expected: 'wo word',
159 description: 'Grammar test for lokatiw case'
160 }
161 ],
162
163 dsb: [
164 {
165 word: 'word',
166 grammarForm: 'instrumental',
167 expected: 'z word',
168 description: 'Grammar test for instrumental case'
169 },
170 {
171 word: 'word',
172 grammarForm: 'lokatiw',
173 expected: 'wo word',
174 description: 'Grammar test for lokatiw case'
175 }
176 ],
177
178 hy: [
179 {
180 word: 'Մաունա',
181 grammarForm: 'genitive',
182 expected: 'Մաունայի',
183 description: 'Grammar test for genitive case'
184 },
185 {
186 word: 'հետո',
187 grammarForm: 'genitive',
188 expected: 'հետոյի',
189 description: 'Grammar test for genitive case'
190 },
191 {
192 word: 'գիրք',
193 grammarForm: 'genitive',
194 expected: 'գրքի',
195 description: 'Grammar test for genitive case'
196 },
197 {
198 word: 'ժամանակի',
199 grammarForm: 'genitive',
200 expected: 'ժամանակիի',
201 description: 'Grammar test for genitive case'
202 }
203 ],
204
205 fi: [
206 {
207 word: 'talo',
208 grammarForm: 'genitive',
209 expected: 'talon',
210 description: 'Grammar test for genitive case'
211 },
212 {
213 word: 'linux',
214 grammarForm: 'genitive',
215 expected: 'linuxin',
216 description: 'Grammar test for genitive case'
217 },
218 {
219 word: 'talo',
220 grammarForm: 'elative',
221 expected: 'talosta',
222 description: 'Grammar test for elative case'
223 },
224 {
225 word: 'pastöroitu',
226 grammarForm: 'partitive',
227 expected: 'pastöroitua',
228 description: 'Grammar test for partitive case'
229 },
230 {
231 word: 'talo',
232 grammarForm: 'partitive',
233 expected: 'taloa',
234 description: 'Grammar test for partitive case'
235 },
236 {
237 word: 'talo',
238 grammarForm: 'illative',
239 expected: 'taloon',
240 description: 'Grammar test for illative case'
241 },
242 {
243 word: 'linux',
244 grammarForm: 'inessive',
245 expected: 'linuxissa',
246 description: 'Grammar test for inessive case'
247 }
248 ],
249
250 ru: [
251 {
252 word: 'тесть',
253 grammarForm: 'genitive',
254 expected: 'тестя',
255 description: 'Grammar test for genitive case, тесть -> тестя'
256 },
257 {
258 word: 'привилегия',
259 grammarForm: 'genitive',
260 expected: 'привилегии',
261 description: 'Grammar test for genitive case, привилегия -> привилегии'
262 },
263 {
264 word: 'установка',
265 grammarForm: 'genitive',
266 expected: 'установки',
267 description: 'Grammar test for genitive case, установка -> установки'
268 },
269 {
270 word: 'похоти',
271 grammarForm: 'genitive',
272 expected: 'похотей',
273 description: 'Grammar test for genitive case, похоти -> похотей'
274 },
275 {
276 word: 'доводы',
277 grammarForm: 'genitive',
278 expected: 'доводов',
279 description: 'Grammar test for genitive case, доводы -> доводов'
280 },
281 {
282 word: 'песчаник',
283 grammarForm: 'genitive',
284 expected: 'песчаника',
285 description: 'Grammar test for genitive case, песчаник -> песчаника'
286 },
287 {
288 word: 'данные',
289 grammarForm: 'genitive',
290 expected: 'данных',
291 description: 'Grammar test for genitive case, данные -> данных'
292 },
293 {
294 word: 'тесть',
295 grammarForm: 'prepositional',
296 expected: 'тесте',
297 description: 'Grammar test for prepositional case, тесть -> тесте'
298 },
299 {
300 word: 'привилегия',
301 grammarForm: 'prepositional',
302 expected: 'привилегии',
303 description: 'Grammar test for prepositional case, привилегия -> привилегии'
304 },
305 {
306 word: 'установка',
307 grammarForm: 'prepositional',
308 expected: 'установке',
309 description: 'Grammar test for prepositional case, установка -> установке'
310 },
311 {
312 word: 'похоти',
313 grammarForm: 'prepositional',
314 expected: 'похотях',
315 description: 'Grammar test for prepositional case, похоти -> похотях'
316 },
317 {
318 word: 'доводы',
319 grammarForm: 'prepositional',
320 expected: 'доводах',
321 description: 'Grammar test for prepositional case, доводы -> доводах'
322 },
323 {
324 word: 'Викисклад',
325 grammarForm: 'prepositional',
326 expected: 'Викискладе',
327 description: 'Grammar test for prepositional case, Викисклад -> Викискладе'
328 },
329 {
330 word: 'Викисклад',
331 grammarForm: 'genitive',
332 expected: 'Викисклада',
333 description: 'Grammar test for genitive case, Викисклад -> Викисклада'
334 },
335 {
336 word: 'песчаник',
337 grammarForm: 'prepositional',
338 expected: 'песчанике',
339 description: 'Grammar test for prepositional case, песчаник -> песчанике'
340 },
341 {
342 word: 'данные',
343 grammarForm: 'prepositional',
344 expected: 'данных',
345 description: 'Grammar test for prepositional case, данные -> данных'
346 },
347 {
348 word: 'русский',
349 grammarForm: 'languagegen',
350 expected: 'русского',
351 description: 'Grammar test for languagegen case, русский -> русского'
352 },
353 {
354 word: 'немецкий',
355 grammarForm: 'languagegen',
356 expected: 'немецкого',
357 description: 'Grammar test for languagegen case, немецкий -> немецкого'
358 },
359 {
360 word: 'иврит',
361 grammarForm: 'languagegen',
362 expected: 'иврита',
363 description: 'Grammar test for languagegen case, иврит -> иврита'
364 },
365 {
366 word: 'эсперанто',
367 grammarForm: 'languagegen',
368 expected: 'эсперанто',
369 description: 'Grammar test for languagegen case, эсперанто -> эсперанто'
370 },
371 {
372 word: 'русский',
373 grammarForm: 'languageprep',
374 expected: 'русском',
375 description: 'Grammar test for languageprep case, русский -> русском'
376 },
377 {
378 word: 'немецкий',
379 grammarForm: 'languageprep',
380 expected: 'немецком',
381 description: 'Grammar test for languageprep case, немецкий -> немецком'
382 },
383 {
384 word: 'идиш',
385 grammarForm: 'languageprep',
386 expected: 'идише',
387 description: 'Grammar test for languageprep case, идиш -> идише'
388 },
389 {
390 word: 'эсперанто',
391 grammarForm: 'languageprep',
392 expected: 'эсперанто',
393 description: 'Grammar test for languageprep case, эсперанто -> эсперанто'
394 },
395 {
396 word: 'русский',
397 grammarForm: 'languageadverb',
398 expected: 'по-русски',
399 description: 'Grammar test for languageadverb case, русский -> по-русски'
400 },
401 {
402 word: 'немецкий',
403 grammarForm: 'languageadverb',
404 expected: 'по-немецки',
405 description: 'Grammar test for languageadverb case, немецкий -> по-немецки'
406 },
407 {
408 word: 'иврит',
409 grammarForm: 'languageadverb',
410 expected: 'на иврите',
411 description: 'Grammar test for languageadverb case, иврит -> на иврите'
412 },
413 {
414 word: 'эсперанто',
415 grammarForm: 'languageadverb',
416 expected: 'на эсперанто',
417 description: 'Grammar test for languageadverb case, эсперанто -> на эсперанто'
418 },
419 {
420 word: 'гуарани',
421 grammarForm: 'languageadverb',
422 expected: 'на языке гуарани',
423 description: 'Grammar test for languageadverb case, гуарани -> на языке гуарани'
424 }
425 ],
426
427 hu: [
428 {
429 word: 'Wikipédiá',
430 grammarForm: 'rol',
431 expected: 'Wikipédiáról',
432 description: 'Grammar test for rol case'
433 },
434 {
435 word: 'Wikipédiá',
436 grammarForm: 'ba',
437 expected: 'Wikipédiába',
438 description: 'Grammar test for ba case'
439 },
440 {
441 word: 'Wikipédiá',
442 grammarForm: 'k',
443 expected: 'Wikipédiák',
444 description: 'Grammar test for k case'
445 }
446 ],
447
448 ga: [
449 {
450 word: 'an Domhnach',
451 grammarForm: 'ainmlae',
452 expected: 'Dé Domhnaigh',
453 description: 'Grammar test for ainmlae case'
454 },
455 {
456 word: 'an Luan',
457 grammarForm: 'ainmlae',
458 expected: 'Dé Luain',
459 description: 'Grammar test for ainmlae case'
460 },
461 {
462 word: 'an Satharn',
463 grammarForm: 'ainmlae',
464 expected: 'Dé Sathairn',
465 description: 'Grammar test for ainmlae case'
466 }
467 ],
468
469 uk: [
470 {
471 word: 'Вікіпедія',
472 grammarForm: 'genitive',
473 expected: 'Вікіпедії',
474 description: 'Grammar test for genitive case'
475 },
476 {
477 word: 'Віківиди',
478 grammarForm: 'genitive',
479 expected: 'Віківидів',
480 description: 'Grammar test for genitive case'
481 },
482 {
483 word: 'Вікіцитати',
484 grammarForm: 'genitive',
485 expected: 'Вікіцитат',
486 description: 'Grammar test for genitive case'
487 },
488 {
489 word: 'Вікіпідручник',
490 grammarForm: 'genitive',
491 expected: 'Вікіпідручника',
492 description: 'Grammar test for genitive case'
493 },
494 {
495 word: 'Вікіпедія',
496 grammarForm: 'accusative',
497 expected: 'Вікіпедію',
498 description: 'Grammar test for accusative case'
499 }
500 ],
501
502 sl: [
503 {
504 word: 'word',
505 grammarForm: 'orodnik',
506 expected: 'z word',
507 description: 'Grammar test for orodnik case'
508 },
509 {
510 word: 'word',
511 grammarForm: 'mestnik',
512 expected: 'o word',
513 description: 'Grammar test for mestnik case'
514 }
515 ],
516
517 os: [
518 {
519 word: 'бæстæ',
520 grammarForm: 'genitive',
521 expected: 'бæсты',
522 description: 'Grammar test for genitive case'
523 },
524 {
525 word: 'бæстæ',
526 grammarForm: 'allative',
527 expected: 'бæстæм',
528 description: 'Grammar test for allative case'
529 },
530 {
531 word: 'Тигр',
532 grammarForm: 'dative',
533 expected: 'Тигрæн',
534 description: 'Grammar test for dative case'
535 },
536 {
537 word: 'цъити',
538 grammarForm: 'dative',
539 expected: 'цъитийæн',
540 description: 'Grammar test for dative case'
541 },
542 {
543 word: 'лæппу',
544 grammarForm: 'genitive',
545 expected: 'лæппуйы',
546 description: 'Grammar test for genitive case'
547 },
548 {
549 word: '2011',
550 grammarForm: 'equative',
551 expected: '2011-ау',
552 description: 'Grammar test for equative case'
553 }
554 ],
555
556 la: [
557 {
558 word: 'Translatio',
559 grammarForm: 'genitive',
560 expected: 'Translationis',
561 description: 'Grammar test for genitive case'
562 },
563 {
564 word: 'Translatio',
565 grammarForm: 'accusative',
566 expected: 'Translationem',
567 description: 'Grammar test for accusative case'
568 },
569 {
570 word: 'Translatio',
571 grammarForm: 'ablative',
572 expected: 'Translatione',
573 description: 'Grammar test for ablative case'
574 }
575 ]
576 };
577
578 $.each( grammarTests, function ( langCode, test ) {
579 if ( langCode === mw.config.get( 'wgUserLanguage' ) ) {
580 grammarTest( langCode, test );
581 }
582 } );
583
584 QUnit.test( 'List to text test', function ( assert ) {
585 assert.equal( mw.language.listToText( [] ), '', 'Blank list' );
586 assert.equal( mw.language.listToText( [ 'a' ] ), 'a', 'Single item' );
587 assert.equal( mw.language.listToText( [ 'a', 'b' ] ), 'a and b', 'Two items' );
588 assert.equal( mw.language.listToText( [ 'a', 'b', 'c' ] ), 'a, b and c', 'More than two items' );
589 } );
590
591 bcp47Tests = [
592 // Extracted from BCP 47 (list not exhaustive)
593 // # 2.1.1
594 [ 'en-ca-x-ca', 'en-CA-x-ca' ],
595 [ 'sgn-be-fr', 'sgn-BE-FR' ],
596 [ 'az-latn-x-latn', 'az-Latn-x-latn' ],
597 // # 2.2
598 [ 'sr-Latn-RS', 'sr-Latn-RS' ],
599 [ 'az-arab-ir', 'az-Arab-IR' ],
600
601 // # 2.2.5
602 [ 'sl-nedis', 'sl-nedis' ],
603 [ 'de-ch-1996', 'de-CH-1996' ],
604
605 // # 2.2.6
606 [
607 'en-latn-gb-boont-r-extended-sequence-x-private',
608 'en-Latn-GB-boont-r-extended-sequence-x-private'
609 ],
610
611 // Examples from BCP 47 Appendix A
612 // # Simple language subtag:
613 [ 'DE', 'de' ],
614 [ 'fR', 'fr' ],
615 [ 'ja', 'ja' ],
616
617 // # Language subtag plus script subtag:
618 [ 'zh-hans', 'zh-Hans' ],
619 [ 'sr-cyrl', 'sr-Cyrl' ],
620 [ 'sr-latn', 'sr-Latn' ],
621
622 // # Extended language subtags and their primary language subtag
623 // # counterparts:
624 [ 'zh-cmn-hans-cn', 'zh-cmn-Hans-CN' ],
625 [ 'cmn-hans-cn', 'cmn-Hans-CN' ],
626 [ 'zh-yue-hk', 'zh-yue-HK' ],
627 [ 'yue-hk', 'yue-HK' ],
628
629 // # Language-Script-Region:
630 [ 'zh-hans-cn', 'zh-Hans-CN' ],
631 [ 'sr-latn-RS', 'sr-Latn-RS' ],
632
633 // # Language-Variant:
634 [ 'sl-rozaj', 'sl-rozaj' ],
635 [ 'sl-rozaj-biske', 'sl-rozaj-biske' ],
636 [ 'sl-nedis', 'sl-nedis' ],
637
638 // # Language-Region-Variant:
639 [ 'de-ch-1901', 'de-CH-1901' ],
640 [ 'sl-it-nedis', 'sl-IT-nedis' ],
641
642 // # Language-Script-Region-Variant:
643 [ 'hy-latn-it-arevela', 'hy-Latn-IT-arevela' ],
644
645 // # Language-Region:
646 [ 'de-de', 'de-DE' ],
647 [ 'en-us', 'en-US' ],
648 [ 'es-419', 'es-419' ],
649
650 // # Private use subtags:
651 [ 'de-ch-x-phonebk', 'de-CH-x-phonebk' ],
652 [ 'az-arab-x-aze-derbend', 'az-Arab-x-aze-derbend' ],
653 /**
654 * Previous test does not reflect the BCP 47 which states:
655 * az-Arab-x-AZE-derbend
656 * AZE being private, it should be lower case, hence the test above
657 * should probably be:
658 * [ 'az-arab-x-aze-derbend', 'az-Arab-x-AZE-derbend' ],
659 */
660
661 // # Private use registry values:
662 [ 'x-whatever', 'x-whatever' ],
663 [ 'qaa-qaaa-qm-x-southern', 'qaa-Qaaa-QM-x-southern' ],
664 [ 'de-qaaa', 'de-Qaaa' ],
665 [ 'sr-latn-qm', 'sr-Latn-QM' ],
666 [ 'sr-qaaa-rs', 'sr-Qaaa-RS' ],
667
668 // # Tags that use extensions
669 [ 'en-us-u-islamcal', 'en-US-u-islamcal' ],
670 [ 'zh-cn-a-myext-x-private', 'zh-CN-a-myext-x-private' ],
671 [ 'en-a-myext-b-another', 'en-a-myext-b-another' ]
672
673 // # Invalid:
674 // de-419-DE
675 // a-DE
676 // ar-a-aaa-b-bbb-a-ccc
677 ];
678
679 QUnit.test( 'mw.language.bcp47', function ( assert ) {
680 bcp47Tests.forEach( function ( data ) {
681 var input = data[ 0 ],
682 expected = data[ 1 ];
683 assert.equal( mw.language.bcp47( input ), expected );
684 } );
685 } );
686 }( mediaWiki, jQuery ) );