diff --git a/Resources/js/translator.js b/Resources/js/translator.js index 66cac94..35bfd04 100644 --- a/Resources/js/translator.js +++ b/Resources/js/translator.js @@ -557,7 +557,6 @@ case 'am': case 'bh': case 'fil': - case 'fr': case 'gun': case 'hi': case 'ln': @@ -568,6 +567,9 @@ case 'wa': return ((number === 0) || (number == 1)) ? 0 : 1; + case 'fr': + return (number != 0 && number % 1000000 == 0) ? 1 : (((number === 0) || (number == 1)) ? 0 : 2); + case 'be': case 'bs': case 'hr': diff --git a/Resources/js/translatorTest.js b/Resources/js/translatorTest.js index 062a43d..8816719 100644 --- a/Resources/js/translatorTest.js +++ b/Resources/js/translatorTest.js @@ -65,18 +65,20 @@ QUnit.test('trans()', function(assert) { }); QUnit.test('transChoice()', function(assert) { - assert.expect(31); + assert.expect(38); Translator.add('foo.plural', '{0} Nothing|[1,Inf[ Many things', 'Foo'); Translator.add('foo.plural.with.args', '{0} Nothing|{1} One thing|[2,Inf[ %count% things', 'Foo'); Translator.add('foo.plural.with.inf', ']-Inf,0[ Underground|{0} Ground 0|{1} First level|[2,Inf[ High level', 'Foo'); Translator.add('complex.plural', '{0} There is no apples|[20,Inf] There are many apples|There is one apple|a_few: There are %count% apples', 'Foo'); + Translator.add('complex.plural', '{0} There is no apples|[20,Inf] There are many apples|There is one apple|a_few: There are %count% apples', 'Foo', 'en'); Translator.add('foo.plural.space.before.interval', ' {0} Nothing| [1,Inf[ Many things', 'Foo'); Translator.add('foo.plural.without.space', '{0}Nothing|[1,Inf[Many things', 'Foo'); Translator.add('foo.single', 'Things', 'Foo'); Translator.add('foo.count.parameter', '[0,1]%count% item|]1,Inf[%count% items', 'Foo'); Translator.add('foo.count.parameter.additional', '[0,Inf[%count% items of %foo%', 'Foo'); Translator.add('foo.count.parameter.overriden', '[0,Inf[%count% items', 'Foo'); + Translator.add('french.million.plural', '%count% jour|%count% de jours|%count% jours', 'Foo', 'fr'); // Basic assert.equal(Translator.transChoice('foo.plural', null, {}, 'Foo'), '{0} Nothing|[1,Inf[ Many things', 'Returns the correct message for the given key'); @@ -97,10 +99,10 @@ QUnit.test('transChoice()', function(assert) { assert.equal(Translator.transChoice('foo.plural.with.inf', 1, {}, 'Foo'), 'First level', 'number = 1 returns the {1} part of the message'); assert.equal(Translator.transChoice('foo.plural.with.inf', 10000, {}, 'Foo'), 'High level', 'number = 1000 returns the [2,Inf[ part of the message'); - assert.equal(Translator.transChoice('complex.plural', 0, {}, 'Foo'), 'There is no apples', 'number = 0 returns the {0} part of the message'); - assert.equal(Translator.transChoice('complex.plural', 1, {}, 'Foo'), 'There is one apple', 'number = 1 returns the standard rule'); - assert.equal(Translator.transChoice('complex.plural', 9, { count: 9 }, 'Foo'), 'There are 9 apples', 'number = 10 returns the "a_few" part of the message'); - assert.equal(Translator.transChoice('complex.plural', 20, {}, 'Foo'), 'There are many apples', 'number = 20 returns the [20,Inf] part of the message'); + assert.equal(Translator.transChoice('complex.plural', 0, {}, 'Foo', 'en'), 'There is no apples', 'number = 0 returns the {0} part of the message'); + assert.equal(Translator.transChoice('complex.plural', 1, {}, 'Foo', 'en'), 'There is one apple', 'number = 1 returns the standard rule'); + assert.equal(Translator.transChoice('complex.plural', 9, { count: 9 }, 'Foo', 'en'), 'There are 9 apples', 'number = 10 returns the "a_few" part of the message'); + assert.equal(Translator.transChoice('complex.plural', 20, {}, 'Foo', 'en'), 'There are many apples', 'number = 20 returns the [20,Inf] part of the message'); // Translations with spaces before intervals assert.equal(Translator.transChoice('foo.plural.space.before.interval', 0, {}, 'Foo'), 'Nothing', 'number = 0 returns the {0} part of the message'); @@ -112,6 +114,15 @@ QUnit.test('transChoice()', function(assert) { assert.equal(Translator.transChoice('foo.plural.without.space', 1, {}, 'Foo'), 'Many things', 'number = 1 returns the [1,Inf[ part of the message'); assert.equal(Translator.transChoice('foo.plural.without.space', 100, {}, 'Foo'), 'Many things', 'number = 100 returns the [1,Inf[ part of the message'); + // French pluralization + assert.equal(Translator.transChoice('french.million.plural', 0, { count: 0 }, 'Foo', 'fr'), '0 jour', 'French number = 0 returns the one form'); + assert.equal(Translator.transChoice('french.million.plural', 1, { count: 1 }, 'Foo', 'fr'), '1 jour', 'French number = 1 returns the one form'); + assert.equal(Translator.transChoice('french.million.plural', 2, { count: 2 }, 'Foo', 'fr'), '2 jours', 'French number = 2 returns the other form'); + assert.equal(Translator.transChoice('french.million.plural', 999999, { count: 999999 }, 'Foo', 'fr'), '999999 jours', 'French number = 999999 returns the other form'); + assert.equal(Translator.transChoice('french.million.plural', 1000000, { count: 1000000 }, 'Foo', 'fr'), '1000000 de jours', 'French number = 1000000 returns the many form'); + assert.equal(Translator.transChoice('french.million.plural', 1000001, { count: 1000001 }, 'Foo', 'fr'), '1000001 jours', 'French number = 1000001 returns the other form'); + assert.equal(Translator.transChoice('french.million.plural', 2000000, { count: 2000000 }, 'Foo', 'fr'), '2000000 de jours', 'French number = 2000000 returns the many form'); + // Fallback to default translation assert.equal(Translator.transChoice('foo.single', 1, {}, 'Foo'), 'Things', 'number = 1 returns the single available translation'); assert.equal(Translator.transChoice('foo.single', 2, {}, 'Foo'), 'Things', 'number = 2 returns the single available translation'); diff --git a/Resources/public/js/translator.min.js b/Resources/public/js/translator.min.js index 9afabc0..4aa3a05 100644 --- a/Resources/public/js/translator.min.js +++ b/Resources/public/js/translator.min.js @@ -2,4 +2,4 @@ * @author William DURAND * @license MIT Licensed */ -!function(e,a){"object"==typeof module&&module.exports?module.exports=a(require("intl-messageformat")):"function"==typeof define&&define.amd?define(["intl-messageformat"],a):e.Translator=a(e.IntlMessageFormat)}("undefined"!=typeof self?self:this,function(e){"use strict";function a(e,a){var s,n=g.placeHolderPrefix,r=g.placeHolderSuffix;for(s in a){var t=new RegExp(n+s+r,"g");if(t.test(e)){var c=String(a[s]).replace(new RegExp("\\$","g"),"$$$$");e=e.replace(t,c)}}return e}function s(e,a,s,r,t,c){var i=s||r||t,l=a,u=c||{},d=i.split("_")[0];if(u.isICU=!1,!(i in o))if(d in o)i=d;else{if(!(t in o))return e;i=t}if(void 0===l||null===l)for(var h=0;h2&&(m=i.length,g=i.split(/[\s_]+/),v=g[g.length-1],b=v.length,1!==g.length);)if(i=i.substring(0,m-(b+1)),n(i,l,e))return o[i][l][e];return n(t,l,e)?o[t][l][e]:e}function n(e,a,s){return e in o&&(a in o[e]&&s in o[e][a])}function r(e,a,s){var n,r,i=[],l=[],o=e.split(g.pluralSeparator),u=[];for(n=0;n=b:a>b)&&("]"===u[6]?a<=I:a3&&(s=s.split("_")[0]),s){case"bo":case"dz":case"id":case"ja":case"jv":case"ka":case"km":case"kn":case"ko":case"ms":case"th":case"tr":case"vi":case"zh":return 0;case"af":case"az":case"bn":case"bg":case"ca":case"da":case"de":case"el":case"en":case"eo":case"es":case"et":case"eu":case"fa":case"fi":case"fo":case"fur":case"fy":case"gl":case"gu":case"ha":case"he":case"hu":case"is":case"it":case"ku":case"lb":case"ml":case"mn":case"mr":case"nah":case"nb":case"ne":case"nl":case"nn":case"no":case"om":case"or":case"pa":case"pap":case"ps":case"pt":case"so":case"sq":case"sv":case"sw":case"ta":case"te":case"tk":case"ur":case"zu":return 1==e?0:1;case"am":case"bh":case"fil":case"fr":case"gun":case"hi":case"ln":case"mg":case"nso":case"xbr":case"ti":case"wa":return 0===e||1==e?0:1;case"be":case"bs":case"hr":case"ru":case"sr":case"uk":return e%10==1&&e%100!=11?0:e%10>=2&&e%10<=4&&(e%100<10||e%100>=20)?1:2;case"cs":case"sk":return 1==e?0:e>=2&&e<=4?1:2;case"ga":return 1==e?0:2==e?1:2;case"lt":return e%10==1&&e%100!=11?0:e%10>=2&&(e%100<10||e%100>=20)?1:2;case"sl":return e%100==1?0:e%100==2?1:e%100==3||e%100==4?2:3;case"mk":return e%10==1?0:1;case"mt":return 1==e?0:0===e||e%100>1&&e%100<11?1:e%100>10&&e%100<20?2:3;case"lv":return 0===e?0:e%10==1&&e%100!=11?1:2;case"pl":return 1==e?0:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?1:2;case"cy":return 1==e?0:2==e?1:8==e||11==e?2:3;case"ro":return 1==e?0:0===e||e%100>0&&e%100<20?1:2;case"ar":return 0===e?0:1==e?1:2==e?2:e>=3&&e<=10?3:e>=11&&e<=99?4:5;default:return 0}}function i(e,a){for(var s=0;s2&&(m=i.length,g=i.split(/[\s_]+/),v=g[g.length-1],b=v.length,1!==g.length);){if(i=i.substring(0,m-(b+1)),r(i,l+p,e))return u.isICU=!0,o[i][l+p][e];if(r(i,l,e))return o[i][l][e]}return r(t,l+p,e)?(u.isICU=!0,o[t][l+p][e]):r(t,l,e)?o[t][l][e]:e}function r(e,a,s){return e in o&&(a in o[e]&&s in o[e][a])}function n(e,a,s){var r,n,i=[],l=[],o=e.split(g.pluralSeparator),u=[];for(r=0;r=b:a>b)&&("]"===u[6]?a<=I:a3&&(s=s.split("_")[0]),s){case"bo":case"dz":case"id":case"ja":case"jv":case"ka":case"km":case"kn":case"ko":case"ms":case"th":case"tr":case"vi":case"zh":return 0;case"af":case"az":case"bn":case"bg":case"ca":case"da":case"de":case"el":case"en":case"eo":case"es":case"et":case"eu":case"fa":case"fi":case"fo":case"fur":case"fy":case"gl":case"gu":case"ha":case"he":case"hu":case"is":case"it":case"ku":case"lb":case"ml":case"mn":case"mr":case"nah":case"nb":case"ne":case"nl":case"nn":case"no":case"om":case"or":case"pa":case"pap":case"ps":case"pt":case"so":case"sq":case"sv":case"sw":case"ta":case"te":case"tk":case"ur":case"zu":return 1==e?0:1;case"am":case"bh":case"fil":case"gun":case"hi":case"ln":case"mg":case"nso":case"xbr":case"ti":case"wa":return 0===e||1==e?0:1;case"fr":return 0!=e&&e%1e6==0?1:0===e||1==e?0:2;case"be":case"bs":case"hr":case"ru":case"sr":case"uk":return e%10==1&&e%100!=11?0:e%10>=2&&e%10<=4&&(e%100<10||e%100>=20)?1:2;case"cs":case"sk":return 1==e?0:e>=2&&e<=4?1:2;case"ga":return 1==e?0:2==e?1:2;case"lt":return e%10==1&&e%100!=11?0:e%10>=2&&(e%100<10||e%100>=20)?1:2;case"sl":return e%100==1?0:e%100==2?1:e%100==3||e%100==4?2:3;case"mk":return e%10==1?0:1;case"mt":return 1==e?0:0===e||e%100>1&&e%100<11?1:e%100>10&&e%100<20?2:3;case"lv":return 0===e?0:e%10==1&&e%100!=11?1:2;case"pl":return 1==e?0:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?1:2;case"cy":return 1==e?0:2==e?1:8==e||11==e?2:3;case"ro":return 1==e?0:0===e||e%100>0&&e%100<20?1:2;case"ar":return 0===e?0:1==e?1:2==e?2:e>=3&&e<=10?3:e>=11&&e<=99?4:5;default:return 0}}function i(e,a){for(var s=0;s