diff --git a/README.md b/README.md index a54471fa2..e1be35493 100644 --- a/README.md +++ b/README.md @@ -205,7 +205,7 @@ requirements. See table below. | Currency module | cldr/main/`locale`/currencies.json
cldr/supplemental/currencyData.json
+CLDR JSON files from number module
+CLDR JSON files from plural module for name style support | | Date module | cldr/main/`locale`/ca-gregorian.json
cldr/main/`locale`/timeZoneNames.json
cldr/supplemental/timeData.json
cldr/supplemental/weekData.json
+CLDR JSON files from number module | | Number module | cldr/main/`locale`/numbers.json
cldr/supplemental/numberingSystems.json | -| Plural module | cldr/supplemental/plurals.json | +| Plural module | cldr/supplemental/plurals.json (for cardinals)
cldr/supplemental/ordinals.json (for ordinals) | *(b) How am I supposed to get and load CLDR content?* @@ -433,24 +433,32 @@ to you in different flavors): ### Plural module -- **`.pluralGenerator()`** +- **`.pluralGenerator( [options] )`** Return a function that returns the value's corresponding plural group: `zero`, `one`, `two`, `few`, `many`, or `other`. + The function may be used for cardinals or ordinals. + ```javascript .pluralGenerator()( 0 ) // > "other" .pluralGenerator()( 1 ) // > "one" + + .pluralGenerator({ type: "ordinal" })( 1 ) + // > "one" + + .pluralGenerator({ type: "ordinal" })( 2 ) + // > "two" ``` [Read more...](doc/api/plural/plural-generator.md) -- **`.plural( value )`** +- **`.plural( value[, options ] )`** - Alias for `.pluralGenerator()( value )`. + Alias for `.pluralGenerator( [options] )( value )`. ## Error reference diff --git a/doc/api/plural/plural-generator.md b/doc/api/plural/plural-generator.md index 0eec91996..9f26535b0 100644 --- a/doc/api/plural/plural-generator.md +++ b/doc/api/plural/plural-generator.md @@ -1,4 +1,4 @@ -## .pluralGenerator() ➜ function( value ) +## .pluralGenerator( [options] ) ➜ function( value ) It supports the creation of internationalized messages with plural inflection by returning a function that returns the value's plural group: `zero`, `one`, @@ -9,13 +9,24 @@ to return the plural group. ### Parameters +**options** Optional + +A JSON object including none or any of the following options. + +> **type** Optional +> +> String `cardinal` (default), or `ordinal`. + **value** A Number for which to return the plural group. ### Example -Prior to using any plural method, you must load `supplemental/plurals.json`. +Prior to using any plural method, you must load either +`supplemental/plurals.json` for cardinals or `supplemental/ordinals.json` for +ordinals. + Read [CLDR content][] if you need more information. [CLDR content]: ../../../README.md#2-cldr-content @@ -27,6 +38,8 @@ default locale. var plural; Globalize.locale( "en" ); + +// Cardinals plural = Globalize.pluralGenerator(); plural( 0 ); @@ -37,6 +50,18 @@ plural( 1 ); plural( 2 ); // > "other" + +// Ordinals +plural = Globalize.pluralGenerator({ type: "ordinal" }); + +plural( 0 ); +// > "other" + +plural( 1 ); +// > "one" + +plural( 2 ); +// > "two" ``` You can use the instance method `.pluralGenerator()`, which uses the instance @@ -49,7 +74,7 @@ plural( 1 ); // > "other" ``` -For comparison: +For comparison (cardinals): | | en (English) | ru (Russian) | ar (Arabic) | | --- | --- | --- | --- | @@ -58,3 +83,13 @@ For comparison: | `plural( 2 )` | `other` | `few` | `two` | | `plural( 3 )` | `other` | `few` | `few` | | `plural( 5 )` | `other` | `many` | `few` | + +For comparison (ordinals): + +| | en (English) | ru (Russian) | ar (Arabic) | +| --- | --- | --- | --- | +| `plural( 0, { type: "ordinal" } )` | `other` | `other` | `other` | +| `plural( 1, { type: "ordinal" } )` | `one` | `other` | `other` | +| `plural( 2, { type: "ordinal" } )` | `two` | `other` | `other` | +| `plural( 3, { type: "ordinal" } )` | `few` | `other` | `other` | +| `plural( 5, { type: "ordinal" } )` | `other` | `other` | `other` | diff --git a/src/build/intro-plural.js b/src/build/intro-plural.js index 3269fd1d3..0d82f9df8 100644 --- a/src/build/intro-plural.js +++ b/src/build/intro-plural.js @@ -39,4 +39,5 @@ var validateCldr = Globalize._validateCldr, validateDefaultLocale = Globalize._validateDefaultLocale, validateParameterPresence = Globalize._validateParameterPresence, - validateParameterType = Globalize._validateParameterType; + validateParameterType = Globalize._validateParameterType, + validateParameterTypePlainObject = Globalize._validateParameterTypePlainObject; diff --git a/src/common/validate/parameter-type/plural-type.js b/src/common/validate/parameter-type/plural-type.js new file mode 100644 index 000000000..8991f1907 --- /dev/null +++ b/src/common/validate/parameter-type/plural-type.js @@ -0,0 +1,14 @@ +define([ + "../parameter-type" +], function( validateParameterType ) { + +return function( value, name ) { + validateParameterType( + value, + name, + value === undefined || value === "cardinal" || value === "ordinal", + "String \"cardinal\" or \"ordinal\"" + ); +}; + +}); diff --git a/src/plural.js b/src/plural.js index 4b908e180..122e1100e 100644 --- a/src/plural.js +++ b/src/plural.js @@ -7,11 +7,14 @@ define([ "./common/validate/parameter-presence", "./common/validate/parameter-type", "./common/validate/parameter-type/number", + "./common/validate/parameter-type/plain-object", + "./common/validate/parameter-type/plural-type", "cldr/event", "cldr/supplemental" ], function( Cldr, MakePlural, Globalize, validateCldr, validateDefaultLocale, - validateParameterPresence, validateParameterType, validateParameterTypeNumber ) { + validateParameterPresence, validateParameterType, validateParameterTypeNumber, + validateParameterTypePlainObject, validateParameterTypePluralType ) { /** * .plural( value ) @@ -22,14 +25,14 @@ define([ * value given locale. */ Globalize.plural = -Globalize.prototype.plural = function( value ) { +Globalize.prototype.plural = function( value, options ) { validateParameterPresence( value, "value" ); validateParameterTypeNumber( value, "value" ); - return this.pluralGenerator()( value ); + return this.pluralGenerator( options )( value ); }; /** - * .pluralGenerator() + * .pluralGenerator( [options] ) * * Return a plural function (of the form below). * @@ -41,23 +44,33 @@ Globalize.prototype.plural = function( value ) { * default/instance locale. */ Globalize.pluralGenerator = -Globalize.prototype.pluralGenerator = function() { - var cldr, plural; +Globalize.prototype.pluralGenerator = function( options ) { + var cldr, isOrdinal, plural, type; + validateParameterTypePlainObject( options, "options" ); + + options = options || {}; + type = options.type || "cardinal"; cldr = this.cldr; + validateParameterTypePluralType( options.type, "options.type" ); + validateDefaultLocale( cldr ); + isOrdinal = type === "ordinal"; + cldr.on( "get", validateCldr ); - cldr.supplemental( "plurals-type-cardinal/{language}" ); + cldr.supplemental([ "plurals-type-" + type, "{language}" ]); cldr.off( "get", validateCldr ); - // Set CLDR data - MakePlural.rules = { - cardinal: cldr.supplemental( "plurals-type-cardinal" ) - }; + MakePlural.rules = {}; + MakePlural.rules[ type ] = cldr.supplemental( "plurals-type-" + type ); - plural = MakePlural( cldr.attributes.language, { "no_tests": true } ); + plural = MakePlural( cldr.attributes.language, { + "no_tests": true, + "ordinals": isOrdinal, + "no_cardinals": isOrdinal + } ); return function( value ) { validateParameterPresence( value, "value" ); diff --git a/test/functional/plural/plural.js b/test/functional/plural/plural.js index 1a5ffc742..3f628ea4a 100644 --- a/test/functional/plural/plural.js +++ b/test/functional/plural/plural.js @@ -2,13 +2,15 @@ define([ "globalize", "json!cldr-data/supplemental/likelySubtags.json", "json!cldr-data/supplemental/plurals.json", + "json!cldr-data/supplemental/ordinals.json", "../../util", "globalize/plural" -], function( Globalize, likelySubtags, plurals, util ) { +], function( Globalize, likelySubtags, plurals, ordinals, util ) { function extraSetup() { Globalize.load( plurals ); + Globalize.load( ordinals ); // Temporary fix due to CLDR v26 regression about pt_BR plural // http://unicode.org/cldr/trac/ticket/7178 @@ -47,6 +49,12 @@ QUnit.test( "should validate parameters", function( assert ) { Globalize.plural( invalidValue ); }; }); + + util.assertPlainObjectParameter( assert, "options", function( invalidOptions ) { + return function() { + Globalize.plural( 0, invalidOptions ); + }; + }); }); QUnit.test( "should validate CLDR content", function( assert ) { @@ -67,6 +75,14 @@ QUnit.test( "should return plural form", function( assert ) { assert.equal( Globalize( "en" ).plural( 0.14 ), "other" ); assert.equal( Globalize( "en" ).plural( 3.14 ), "other" ); + assert.equal( Globalize( "en" ).plural( 0, { type: "ordinal" } ), "other" ); + assert.equal( Globalize( "en" ).plural( 1, { type: "ordinal" } ), "one" ); + assert.equal( Globalize( "en" ).plural( 2, { type: "ordinal" } ), "two" ); + assert.equal( Globalize( "en" ).plural( 3, { type: "ordinal" } ), "few" ); + assert.equal( Globalize( "en" ).plural( 1412, { type: "ordinal" } ), "other" ); + assert.equal( Globalize( "en" ).plural( 0.14, { type: "ordinal" } ), "other" ); + assert.equal( Globalize( "en" ).plural( 3.14, { type: "ordinal" } ), "other" ); + assert.equal( Globalize( "ar" ).plural( 0 ), "zero" ); assert.equal( Globalize( "ar" ).plural( 1 ), "one" ); assert.equal( Globalize( "ar" ).plural( 2 ), "two" ); @@ -87,6 +103,10 @@ QUnit.test( "should return plural form", function( assert ) { assert.equal( Globalize( "ar" ).plural( 199 ), "many" ); assert.equal( Globalize( "ar" ).plural( 3.14 ), "other" ); + [ 0, 1, 2, 3, 9, 10, 11, 99, 100, 101, 3.14 ].forEach(function( value ) { + assert.equal( Globalize( "ar" ).plural( value, { type: "ordinal" } ), "other" ); + }); + assert.equal( Globalize( "ja" ).plural( 0 ), "other" ); assert.equal( Globalize( "ja" ).plural( 1 ), "other" ); assert.equal( Globalize( "ja" ).plural( 2 ), "other" );