123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477 |
- // Copyright 2010 The Closure Library Authors. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS-IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- goog.provide('goog.i18n.MessageFormatTest');
- goog.setTestOnly('goog.i18n.MessageFormatTest');
- goog.require('goog.i18n.MessageFormat');
- goog.require('goog.i18n.NumberFormatSymbols_hr');
- goog.require('goog.i18n.pluralRules');
- goog.require('goog.testing.PropertyReplacer');
- goog.require('goog.testing.jsunit');
- // Testing stubs that autoreset after each test run.
- var stubs = new goog.testing.PropertyReplacer();
- function tearDown() {
- stubs.reset();
- }
- function testEmptyPattern() {
- var fmt = new goog.i18n.MessageFormat('');
- assertEquals('', fmt.format({}));
- }
- function testMissingLeftCurlyBrace() {
- var err = assertThrows(function() {
- var fmt = new goog.i18n.MessageFormat('\'\'{}}');
- fmt.format({});
- });
- assertEquals('Assertion failed: No matching { for }.', err.message);
- }
- function testTooManyLeftCurlyBraces() {
- var err = assertThrows(function() {
- var fmt = new goog.i18n.MessageFormat('{} {');
- fmt.format({});
- });
- assertEquals(
- 'Assertion failed: There are mismatched { or } in the pattern.',
- err.message);
- }
- function testSimpleReplacement() {
- var fmt = new goog.i18n.MessageFormat('New York in {SEASON} is nice.');
- assertEquals(
- 'New York in the Summer is nice.', fmt.format({'SEASON': 'the Summer'}));
- }
- function testSimpleSelect() {
- var fmt = new goog.i18n.MessageFormat(
- '{GENDER, select,' +
- 'male {His} ' +
- 'female {Her} ' +
- 'other {Its}}' +
- ' bicycle is {GENDER, select, male {blue} female {red} other {green}}.');
- assertEquals('His bicycle is blue.', fmt.format({'GENDER': 'male'}));
- assertEquals('Her bicycle is red.', fmt.format({'GENDER': 'female'}));
- assertEquals('Its bicycle is green.', fmt.format({'GENDER': 'other'}));
- assertEquals('Its bicycle is green.', fmt.format({'GENDER': 'whatever'}));
- }
- function testSimplePlural() {
- var fmt = new goog.i18n.MessageFormat(
- 'I see {NUM_PEOPLE, plural, offset:1 ' +
- '=0 {no one at all in {PLACE}.} ' +
- '=1 {{PERSON} in {PLACE}.} ' +
- 'one {{PERSON} and one other person in {PLACE}.} ' +
- 'other {{PERSON} and # other people in {PLACE}.}}');
- assertEquals(
- 'I see no one at all in Belgrade.',
- fmt.format({'NUM_PEOPLE': 0, 'PLACE': 'Belgrade'}));
- assertEquals(
- 'I see Markus in Berlin.',
- fmt.format({'NUM_PEOPLE': 1, 'PERSON': 'Markus', 'PLACE': 'Berlin'}));
- assertEquals(
- 'I see Mark and one other person in Athens.',
- fmt.format({'NUM_PEOPLE': 2, 'PERSON': 'Mark', 'PLACE': 'Athens'}));
- assertEquals(
- 'I see Cibu and 99 other people in the cubes.',
- fmt.format({'NUM_PEOPLE': 100, 'PERSON': 'Cibu', 'PLACE': 'the cubes'}));
- }
- function testSimplePluralNoOffset() {
- var fmt = new goog.i18n.MessageFormat(
- 'I see {NUM_PEOPLE, plural, ' +
- '=0 {no one at all} ' +
- '=1 {{PERSON}} ' +
- 'one {{PERSON} and one other person} ' +
- 'other {{PERSON} and # other people}} in {PLACE}.');
- assertEquals(
- 'I see no one at all in Belgrade.',
- fmt.format({'NUM_PEOPLE': 0, 'PLACE': 'Belgrade'}));
- assertEquals(
- 'I see Markus in Berlin.',
- fmt.format({'NUM_PEOPLE': 1, 'PERSON': 'Markus', 'PLACE': 'Berlin'}));
- assertEquals(
- 'I see Mark and 2 other people in Athens.',
- fmt.format({'NUM_PEOPLE': 2, 'PERSON': 'Mark', 'PLACE': 'Athens'}));
- assertEquals(
- 'I see Cibu and 100 other people in the cubes.',
- fmt.format({'NUM_PEOPLE': 100, 'PERSON': 'Cibu', 'PLACE': 'the cubes'}));
- }
- function testSelectNestedInPlural() {
- var fmt = new goog.i18n.MessageFormat(
- '{CIRCLES, plural, ' +
- 'one {{GENDER, select, ' +
- ' female {{WHO} added you to her circle} ' +
- ' other {{WHO} added you to his circle}}} ' +
- 'other {{GENDER, select, ' +
- ' female {{WHO} added you to her # circles} ' +
- ' other {{WHO} added you to his # circles}}}}');
- assertEquals(
- 'Jelena added you to her circle',
- fmt.format({'GENDER': 'female', 'WHO': 'Jelena', 'CIRCLES': 1}));
- assertEquals(
- 'Milan added you to his 1,234 circles',
- fmt.format({'GENDER': 'male', 'WHO': 'Milan', 'CIRCLES': 1234}));
- }
- function testPluralNestedInSelect() {
- // Added offset just for testing purposes. It doesn't make sense
- // to have it otherwise.
- var fmt = new goog.i18n.MessageFormat(
- '{GENDER, select, ' +
- 'female {{NUM_GROUPS, plural, ' +
- ' one {{WHO} added you to her group} ' +
- ' other {{WHO} added you to her # groups}}} ' +
- 'other {{NUM_GROUPS, plural, offset:1' +
- ' one {{WHO} added you to his group} ' +
- ' other {{WHO} added you to his # groups}}}}');
- assertEquals(
- 'Jelena added you to her group',
- fmt.format({'GENDER': 'female', 'WHO': 'Jelena', 'NUM_GROUPS': 1}));
- assertEquals(
- 'Milan added you to his 1,233 groups',
- fmt.format({'GENDER': 'male', 'WHO': 'Milan', 'NUM_GROUPS': 1234}));
- }
- function testLiteralOpenCurlyBrace() {
- var fmt = new goog.i18n.MessageFormat(
- "Anna's house" + " has '{0} and # in the roof' and {NUM_COWS} cows.");
- assertEquals(
- "Anna's house has {0} and # in the roof and 5 cows.",
- fmt.format({'NUM_COWS': '5'}));
- }
- function testLiteralClosedCurlyBrace() {
- var fmt = new goog.i18n.MessageFormat(
- "Anna's house" + " has '{'0'} and # in the roof' and {NUM_COWS} cows.");
- assertEquals(
- "Anna's house has {0} and # in the roof and 5 cows.",
- fmt.format({'NUM_COWS': '5'}));
- // Regression for: b/34764827
- assertEquals(
- 'Anna\'s house has {0} and # in the roof and 8 cows.',
- fmt.format({'NUM_COWS': '8'}));
- }
- function testLiteralPoundSign() {
- var fmt = new goog.i18n.MessageFormat(
- "Anna's house" + " has '{0}' and '# in the roof' and {NUM_COWS} cows.");
- assertEquals(
- "Anna's house has {0} and # in the roof and 5 cows.",
- fmt.format({'NUM_COWS': '5'}));
- // Regression for: b/34764827
- assertEquals(
- 'Anna\'s house has {0} and # in the roof and 10 cows.',
- fmt.format({'NUM_COWS': '10'}));
- }
- function testNoLiteralsForSingleQuotes() {
- var fmt =
- new goog.i18n.MessageFormat("Anna's house" + " 'has {NUM_COWS} cows'.");
- assertEquals("Anna's house 'has 5 cows'.", fmt.format({'NUM_COWS': '5'}));
- }
- function testConsecutiveSingleQuotesAreReplacedWithOneSingleQuote() {
- var fmt = new goog.i18n.MessageFormat("Anna''s house a'{''''b'");
- assertEquals("Anna's house a{''b", fmt.format({}));
- }
- function testConsecutiveSingleQuotesBeforeSpecialCharDontCreateLiteral() {
- var fmt = new goog.i18n.MessageFormat("a''{NUM_COWS}'b");
- assertEquals("a'5'b", fmt.format({'NUM_COWS': '5'}));
- }
- function testSerbianSimpleSelect() {
- stubs.set(goog.i18n.pluralRules, 'select', goog.i18n.pluralRules.beSelect_);
- var fmt = new goog.i18n.MessageFormat(
- '{GENDER, select, ' +
- 'female {Njen} other {Njegov}} bicikl je ' +
- '{GENDER, select, female {crven} other {plav}}.');
- assertEquals('Njegov bicikl je plav.', fmt.format({'GENDER': 'male'}));
- assertEquals('Njen bicikl je crven.', fmt.format({'GENDER': 'female'}));
- }
- function testSerbianSimplePlural() {
- stubs.set(goog.i18n.pluralRules, 'select', goog.i18n.pluralRules.beSelect_);
- var fmt = new goog.i18n.MessageFormat(
- 'Ja {NUM_PEOPLE, plural, offset:1 ' +
- '=0 {ne vidim nikoga} ' +
- '=1 {vidim {PERSON}} ' +
- 'one {vidim {PERSON} i jos # osobu} ' +
- 'few {vidim {PERSON} i jos # osobe} ' +
- 'many {vidim {PERSON} i jos # osoba} ' +
- 'other {{PERSON} i jos # osoba}} ' +
- 'u {PLACE}.');
- assertEquals(
- 'Ja ne vidim nikoga u Beogradu.',
- fmt.format({'NUM_PEOPLE': 0, 'PLACE': 'Beogradu'}));
- assertEquals(
- 'Ja vidim Markusa u Berlinu.',
- fmt.format({'NUM_PEOPLE': 1, 'PERSON': 'Markusa', 'PLACE': 'Berlinu'}));
- assertEquals(
- 'Ja vidim Marka i jos 1 osobu u Atini.',
- fmt.format({'NUM_PEOPLE': 2, 'PERSON': 'Marka', 'PLACE': 'Atini'}));
- assertEquals(
- 'Ja vidim Petra i jos 3 osobe u muzeju.',
- fmt.format({'NUM_PEOPLE': 4, 'PERSON': 'Petra', 'PLACE': 'muzeju'}));
- assertEquals(
- 'Ja vidim Cibua i jos 99 osoba u bazenu.',
- fmt.format({'NUM_PEOPLE': 100, 'PERSON': 'Cibua', 'PLACE': 'bazenu'}));
- }
- function testSerbianSimplePluralNoOffset() {
- stubs.set(goog.i18n.pluralRules, 'select', goog.i18n.pluralRules.beSelect_);
- var fmt = new goog.i18n.MessageFormat(
- 'Ja {NUM_PEOPLE, plural, ' +
- '=0 {ne vidim nikoga} ' +
- '=1 {vidim {PERSON}} ' +
- 'one {vidim {PERSON} i jos # osobu} ' +
- 'few {vidim {PERSON} i jos # osobe} ' +
- 'many {vidim {PERSON} i jos # osoba} ' +
- 'other {{PERSON} i jos # osoba}} ' +
- 'u {PLACE}.');
- assertEquals(
- 'Ja ne vidim nikoga u Beogradu.',
- fmt.format({'NUM_PEOPLE': 0, 'PLACE': 'Beogradu'}));
- assertEquals(
- 'Ja vidim Markusa u Berlinu.',
- fmt.format({'NUM_PEOPLE': 1, 'PERSON': 'Markusa', 'PLACE': 'Berlinu'}));
- assertEquals(
- 'Ja vidim Marka i jos 21 osobu u Atini.',
- fmt.format({'NUM_PEOPLE': 21, 'PERSON': 'Marka', 'PLACE': 'Atini'}));
- assertEquals(
- 'Ja vidim Petra i jos 3 osobe u muzeju.',
- fmt.format({'NUM_PEOPLE': 3, 'PERSON': 'Petra', 'PLACE': 'muzeju'}));
- assertEquals(
- 'Ja vidim Cibua i jos 100 osoba u bazenu.',
- fmt.format({'NUM_PEOPLE': 100, 'PERSON': 'Cibua', 'PLACE': 'bazenu'}));
- }
- function testSerbianSelectNestedInPlural() {
- stubs.set(goog.i18n.pluralRules, 'select', goog.i18n.pluralRules.beSelect_);
- stubs.set(goog.i18n, 'NumberFormatSymbols', goog.i18n.NumberFormatSymbols_hr);
- var fmt = new goog.i18n.MessageFormat(
- '{CIRCLES, plural, ' +
- 'one {{GENDER, select, ' +
- ' female {{WHO} vas je dodala u njen # kruzok} ' +
- ' other {{WHO} vas je dodao u njegov # kruzok}}} ' +
- 'few {{GENDER, select, ' +
- ' female {{WHO} vas je dodala u njena # kruzoka} ' +
- ' other {{WHO} vas je dodao u njegova # kruzoka}}} ' +
- 'many {{GENDER, select, ' +
- ' female {{WHO} vas je dodala u njenih # kruzoka} ' +
- ' other {{WHO} vas je dodao u njegovih # kruzoka}}} ' +
- 'other {{GENDER, select, ' +
- ' female {{WHO} vas je dodala u njenih # kruzoka} ' +
- ' other {{WHO} vas je dodao u njegovih # kruzoka}}}}');
- assertEquals(
- 'Jelena vas je dodala u njen 21 kruzok',
- fmt.format({'GENDER': 'female', 'WHO': 'Jelena', 'CIRCLES': 21}));
- assertEquals(
- 'Jelena vas je dodala u njena 3 kruzoka',
- fmt.format({'GENDER': 'female', 'WHO': 'Jelena', 'CIRCLES': 3}));
- assertEquals(
- 'Jelena vas je dodala u njenih 5 kruzoka',
- fmt.format({'GENDER': 'female', 'WHO': 'Jelena', 'CIRCLES': 5}));
- assertEquals(
- 'Milan vas je dodao u njegovih 1.235 kruzoka',
- fmt.format({'GENDER': 'male', 'WHO': 'Milan', 'CIRCLES': 1235}));
- }
- function testFallbackToOtherOptionInPlurals() {
- // Use Arabic plural rules since they have all six cases.
- // Only locale and numbers matter, the actual language of the message
- // does not.
- stubs.set(goog.i18n.pluralRules, 'select', goog.i18n.pluralRules.arSelect_);
- var fmt = new goog.i18n.MessageFormat(
- '{NUM_MINUTES, plural, ' +
- 'other {# minutes}}');
- // These numbers exercise all cases for the arabic plural rules.
- assertEquals('0 minutes', fmt.format({'NUM_MINUTES': 0}));
- assertEquals('1 minutes', fmt.format({'NUM_MINUTES': 1}));
- assertEquals('2 minutes', fmt.format({'NUM_MINUTES': 2}));
- assertEquals('3 minutes', fmt.format({'NUM_MINUTES': 3}));
- assertEquals('11 minutes', fmt.format({'NUM_MINUTES': 11}));
- assertEquals('1.5 minutes', fmt.format({'NUM_MINUTES': 1.5}));
- }
- function testPoundShowsNumberMinusOffsetInAllCases() {
- var fmt = new goog.i18n.MessageFormat(
- '{SOME_NUM, plural, offset:1 ' +
- '=0 {#} =1 {#} =2 {#}one {#} other {#}}');
- assertEquals('-1', fmt.format({'SOME_NUM': '0'}));
- assertEquals('0', fmt.format({'SOME_NUM': '1'}));
- assertEquals('1', fmt.format({'SOME_NUM': '2'}));
- assertEquals('20', fmt.format({'SOME_NUM': '21'}));
- }
- function testSpecialCharactersInParamaterDontChangeFormat() {
- var fmt = new goog.i18n.MessageFormat(
- '{SOME_NUM, plural,' +
- 'other {# {GROUP}}}');
- // Test pound sign.
- assertEquals(
- '10 group#1', fmt.format({'SOME_NUM': '10', 'GROUP': 'group#1'}));
- // Test other special characters in parameters, like { and }.
- assertEquals('10 } {', fmt.format({'SOME_NUM': '10', 'GROUP': '} {'}));
- }
- function testMissingOrInvalidPluralParameter() {
- var fmt = new goog.i18n.MessageFormat(
- '{SOME_NUM, plural,' +
- 'other {result}}');
- // Key name doesn't match A != SOME_NUM.
- assertEquals(
- 'Undefined or invalid parameter - SOME_NUM', fmt.format({A: '10'}));
- // Value is not a number.
- assertEquals(
- 'Undefined or invalid parameter - SOME_NUM',
- fmt.format({'SOME_NUM': 'Value'}));
- }
- function testMissingSelectParameter() {
- var fmt = new goog.i18n.MessageFormat(
- '{GENDER, select,' +
- 'other {result}}');
- // Key name doesn't match A != GENDER.
- assertEquals('Undefined parameter - GENDER', fmt.format({A: 'female'}));
- }
- function testMissingSimplePlaceholder() {
- var fmt = new goog.i18n.MessageFormat('{result}');
- // Key name doesn't match A != result.
- assertEquals('Undefined parameter - result', fmt.format({A: 'none'}));
- }
- function testPluralWithIgnorePound() {
- var fmt = new goog.i18n.MessageFormat(
- '{SOME_NUM, plural,' +
- 'other {# {GROUP}}}');
- // Test pound sign.
- assertEquals(
- '# group#1',
- fmt.formatIgnoringPound({'SOME_NUM': '10', 'GROUP': 'group#1'}));
- // Test other special characters in parameters, like { and }.
- assertEquals(
- '# } {', fmt.formatIgnoringPound({'SOME_NUM': '10', 'GROUP': '} {'}));
- }
- function testSimplePluralWithIgnorePound() {
- var fmt = new goog.i18n.MessageFormat(
- 'I see {NUM_PEOPLE, plural, offset:1 ' +
- '=0 {no one at all in {PLACE}.} ' +
- '=1 {{PERSON} in {PLACE}.} ' +
- 'one {{PERSON} and one other person in {PLACE}.} ' +
- 'other {{PERSON} and # other people in {PLACE}.}}');
- assertEquals(
- 'I see Cibu and # other people in the cubes.',
- fmt.formatIgnoringPound(
- {'NUM_PEOPLE': 100, 'PERSON': 'Cibu', 'PLACE': 'the cubes'}));
- }
- function testSimpleOrdinal() {
- var fmt = new goog.i18n.MessageFormat(
- '{NUM_FLOOR, selectordinal, ' +
- 'one {Take the elevator to the #st floor.}' +
- 'two {Take the elevator to the #nd floor.}' +
- 'few {Take the elevator to the #rd floor.}' +
- 'other {Take the elevator to the #th floor.}}');
- assertEquals(
- 'Take the elevator to the 1st floor.', fmt.format({'NUM_FLOOR': 1}));
- assertEquals(
- 'Take the elevator to the 2nd floor.', fmt.format({'NUM_FLOOR': 2}));
- assertEquals(
- 'Take the elevator to the 3rd floor.', fmt.format({'NUM_FLOOR': 3}));
- assertEquals(
- 'Take the elevator to the 4th floor.', fmt.format({'NUM_FLOOR': 4}));
- assertEquals(
- 'Take the elevator to the 23rd floor.', fmt.format({'NUM_FLOOR': 23}));
- // Esoteric example.
- assertEquals(
- 'Take the elevator to the 0th floor.', fmt.format({'NUM_FLOOR': 0}));
- }
- function testOrdinalWithNegativeValue() {
- var fmt = new goog.i18n.MessageFormat(
- '{NUM_FLOOR, selectordinal, ' +
- 'one {Take the elevator to the #st floor.}' +
- 'two {Take the elevator to the #nd floor.}' +
- 'few {Take the elevator to the #rd floor.}' +
- 'other {Take the elevator to the #th floor.}}');
- try {
- fmt.format({'NUM_FLOOR': -2});
- } catch (e) {
- assertEquals(
- 'Assertion failed: Argument index smaller than offset.', e.message);
- return;
- }
- fail('Expected an error to be thrown');
- }
- function testSimpleOrdinalWithIgnorePound() {
- var fmt = new goog.i18n.MessageFormat(
- '{NUM_FLOOR, selectordinal, ' +
- 'one {Take the elevator to the #st floor.}' +
- 'two {Take the elevator to the #nd floor.}' +
- 'few {Take the elevator to the #rd floor.}' +
- 'other {Take the elevator to the #th floor.}}');
- assertEquals(
- 'Take the elevator to the #th floor.',
- fmt.formatIgnoringPound({'NUM_FLOOR': 100}));
- }
- function testMissingOrInvalidOrdinalParameter() {
- var fmt = new goog.i18n.MessageFormat(
- '{SOME_NUM, selectordinal,' +
- 'other {result}}');
- // Key name doesn't match A != SOME_NUM.
- assertEquals(
- 'Undefined or invalid parameter - SOME_NUM', fmt.format({A: '10'}));
- // Value is not a number.
- assertEquals(
- 'Undefined or invalid parameter - SOME_NUM',
- fmt.format({'SOME_NUM': 'Value'}));
- }
|