Comparing version 1.0.0-alpha.10 to 1.0.0-alpha.11
{ | ||
"name": "globalize", | ||
"version": "1.0.0-alpha.10", | ||
"version": "1.0.0-alpha.11", | ||
"license": "MIT", | ||
@@ -12,7 +12,7 @@ "ignore": [ | ||
"dependencies": { | ||
"cldrjs": "0.3.9", | ||
"cldrjs": "0.3.10", | ||
"cldr-data": ">=25" | ||
}, | ||
"devDependencies": { | ||
"CLDRPluralRuleParser": "santhoshtr/CLDRPluralRuleParser#6b17882b834b1ab8bb3a593fd66529c9822dd6d7", | ||
"make-plural": "eemeli/make-plural.js#2.1.2", | ||
"es5-shim": "3.4.0", | ||
@@ -19,0 +19,0 @@ "qunit": "1.12.0", |
@@ -1,3 +0,3 @@ | ||
/*! | ||
* Globalize v1.0.0-alpha.10 | ||
/** | ||
* Globalize v1.0.0-alpha.11 | ||
* | ||
@@ -10,4 +10,8 @@ * http://github.com/jquery/globalize | ||
* | ||
* Date: 2014-10-22T17:24Z | ||
* Date: 2014-12-03T12:09Z | ||
*/ | ||
/*! | ||
* Globalize v1.0.0-alpha.11 2014-12-03T12:09Z Released under the MIT license | ||
* http://git.io/TrdQbw | ||
*/ | ||
(function( root, factory ) { | ||
@@ -232,2 +236,10 @@ | ||
// ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions?redirectlocale=en-US&redirectslug=JavaScript%2FGuide%2FRegular_Expressions | ||
var regexpEscape = function( string ) { | ||
return string.replace( /([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1" ); | ||
}; | ||
function validateLikelySubtags( cldr ) { | ||
@@ -301,3 +313,3 @@ cldr.once( "get", validateCldr ); | ||
Globalize._isPlainObject = isPlainObject; | ||
Globalize._validate = validate; | ||
Globalize._regexpEscape = regexpEscape; | ||
Globalize._validateCldr = validateCldr; | ||
@@ -309,2 +321,3 @@ Globalize._validateDefaultLocale = validateDefaultLocale; | ||
Globalize._validateParameterType = validateParameterType; | ||
Globalize._validate = validate; | ||
@@ -311,0 +324,0 @@ return Globalize; |
@@ -1,3 +0,3 @@ | ||
/*! | ||
* Globalize v1.0.0-alpha.10 | ||
/** | ||
* Globalize v1.0.0-alpha.11 | ||
* | ||
@@ -10,4 +10,8 @@ * http://github.com/jquery/globalize | ||
* | ||
* Date: 2014-10-22T17:24Z | ||
* Date: 2014-12-03T12:09Z | ||
*/ | ||
/*! | ||
* Globalize v1.0.0-alpha.11 2014-12-03T12:09Z Released under the MIT license | ||
* http://git.io/TrdQbw | ||
*/ | ||
(function( root, factory ) { | ||
@@ -39,2 +43,3 @@ | ||
isPlainObject = Globalize._isPlainObject, | ||
regexpEscape = Globalize._regexpEscape, | ||
validateCldr = Globalize._validateCldr, | ||
@@ -275,3 +280,3 @@ validateDefaultLocale = Globalize._validateDefaultLocale, | ||
var datePatternRe = (/([a-z])\1*|'[^']+'|''|./ig); | ||
var datePatternRe = (/([a-z])\1*|'([^']|'')+'|''|./ig); | ||
@@ -555,3 +560,11 @@ | ||
// Anything else is considered a literal, including [ ,:/.'@#], chinese, japonese, and | ||
// ' literals. | ||
case "'": | ||
current = current.replace( /''/, "'" ); | ||
if ( length > 2 ) { | ||
current = current.slice( 1, -1 ); | ||
} | ||
return current; | ||
// Anything else is considered a literal, including [ ,:/.@#], chinese, japonese, and | ||
// arabic characters. | ||
@@ -1383,7 +1396,7 @@ default: | ||
token.type = "literal"; | ||
if ( current.charAt( 1 ) === "'" ) { | ||
tokenRe = /'/; | ||
} else { | ||
tokenRe = /'[^']+'/; | ||
current = current.replace( /''/, "'" ); | ||
if ( length > 2 ) { | ||
current = current.slice( 1, -1 ); | ||
} | ||
tokenRe = new RegExp( regexpEscape( current ) ); | ||
break; | ||
@@ -1390,0 +1403,0 @@ |
@@ -1,3 +0,3 @@ | ||
/*! | ||
* Globalize v1.0.0-alpha.10 | ||
/** | ||
* Globalize v1.0.0-alpha.11 | ||
* | ||
@@ -10,4 +10,8 @@ * http://github.com/jquery/globalize | ||
* | ||
* Date: 2014-10-22T17:24Z | ||
* Date: 2014-12-03T12:09Z | ||
*/ | ||
/*! | ||
* Globalize v1.0.0-alpha.11 2014-12-03T12:09Z Released under the MIT license | ||
* http://git.io/TrdQbw | ||
*/ | ||
(function( root, factory ) { | ||
@@ -14,0 +18,0 @@ |
@@ -1,3 +0,3 @@ | ||
/*! | ||
* Globalize v1.0.0-alpha.10 | ||
/** | ||
* Globalize v1.0.0-alpha.11 | ||
* | ||
@@ -10,4 +10,8 @@ * http://github.com/jquery/globalize | ||
* | ||
* Date: 2014-10-22T17:24Z | ||
* Date: 2014-12-03T12:09Z | ||
*/ | ||
/*! | ||
* Globalize v1.0.0-alpha.11 2014-12-03T12:09Z Released under the MIT license | ||
* http://git.io/TrdQbw | ||
*/ | ||
(function( root, factory ) { | ||
@@ -22,3 +26,4 @@ | ||
"../globalize", | ||
"cldr/event" | ||
"cldr/event", | ||
"cldr/supplemental" | ||
], factory ); | ||
@@ -37,2 +42,3 @@ } else if ( typeof exports === "object" ) { | ||
var createError = Globalize._createError, | ||
regexpEscape = Globalize._regexpEscape, | ||
validateCldr = Globalize._validateCldr, | ||
@@ -298,3 +304,3 @@ validateDefaultLocale = Globalize._validateDefaultLocale, | ||
var infinitySymbol, maximumFractionDigits, maximumSignificantDigits, minimumFractionDigits, | ||
minimumIntegerDigits, minimumSignificantDigits, nanSymbol, padding, prefix, | ||
minimumIntegerDigits, minimumSignificantDigits, nanSymbol, nuDigitsMap, padding, prefix, | ||
primaryGroupingSize, pattern, ret, round, roundIncrement, secondaryGroupingSize, suffix, | ||
@@ -316,2 +322,3 @@ symbolMap; | ||
symbolMap = properties[ 18 ]; | ||
nuDigitsMap = properties[ 19 ]; | ||
@@ -374,3 +381,3 @@ // NaN | ||
// Padding | ||
// Padding/'([^']|'')+'|''|[.,\-+E%\u2030]/g | ||
// TODO implement here | ||
@@ -380,8 +387,26 @@ | ||
// Symbols | ||
return ret.replace( /'[^']+'|[.,\-+E%\u2030]/g, function( symbol ) { | ||
if ( symbol.charAt( 0 ) === "'" ) { | ||
return symbol; | ||
return ret.replace( /('([^']|'')+'|'')|./g, function( character, literal ) { | ||
// Literals | ||
if ( literal ) { | ||
literal = literal.replace( /''/, "'" ); | ||
if ( literal.length > 2 ) { | ||
literal = literal.slice( 1, -1 ); | ||
} | ||
return literal; | ||
} | ||
return symbolMap[ symbol ]; | ||
// Symbols | ||
character = character.replace( /[.,\-+E%\u2030]/, function( symbol ) { | ||
return symbolMap[ symbol ]; | ||
}); | ||
// Numbering system | ||
if ( nuDigitsMap ) { | ||
character = character.replace( /[0-9]/, function( digit ) { | ||
return nuDigitsMap[ +digit ]; | ||
}); | ||
} | ||
return character; | ||
}); | ||
@@ -394,2 +419,61 @@ }; | ||
/** | ||
* NumberingSystem( cldr ) | ||
* | ||
* - http://www.unicode.org/reports/tr35/tr35-numbers.html#otherNumberingSystems | ||
* - http://cldr.unicode.org/index/bcp47-extension | ||
* - http://www.unicode.org/reports/tr35/#u_Extension | ||
*/ | ||
var numberNumberingSystem = function( cldr ) { | ||
var nu = cldr.attributes[ "u-nu" ]; | ||
if ( nu ) { | ||
if ( nu === "traditio" ) { | ||
nu = "traditional"; | ||
} | ||
if ( [ "native", "traditional", "finance" ].indexOf( nu ) !== -1 ) { | ||
// Unicode locale extension `u-nu` is set using either (native, traditional or | ||
// finance). So, lookup the respective locale's numberingSystem and return it. | ||
return cldr.main([ "numbers/otherNumberingSystems", nu ]); | ||
} | ||
// Unicode locale extension `u-nu` is set with an explicit numberingSystem. Return it. | ||
return nu; | ||
} | ||
// Return the default numberingSystem. | ||
return cldr.main( "numbers/defaultNumberingSystem" ); | ||
}; | ||
/** | ||
* nuMap( cldr ) | ||
* | ||
* @cldr [Cldr instance]. | ||
* | ||
* Return digits map if numbering system is different than `latn`. | ||
*/ | ||
var numberNumberingSystemDigitsMap = function( cldr ) { | ||
var aux, | ||
nu = numberNumberingSystem( cldr ); | ||
if ( nu === "latn" ) { | ||
return; | ||
} | ||
aux = cldr.supplemental([ "numberingSystems", nu ]); | ||
if ( aux._type !== "numeric" ) { | ||
throw createErrorUnsupportedFeature( "`" + aux._type + "` numbering system" ); | ||
} | ||
return aux._digits; | ||
}; | ||
/** | ||
* EBNF representation: | ||
@@ -574,14 +658,2 @@ * | ||
/** | ||
* NumberingSystem( cldr ) | ||
* | ||
* TODO support ( native | traditional | finance ). | ||
*/ | ||
var numberNumberingSystem = function( cldr ) { | ||
return cldr.main( "numbers/defaultNumberingSystem" ); | ||
}; | ||
/** | ||
* Symbol( name, cldr ) | ||
@@ -720,3 +792,4 @@ * | ||
numberSymbol( "nan", cldr ), | ||
numberSymbolMap( cldr ) | ||
numberSymbolMap( cldr ), | ||
numberNumberingSystemDigitsMap( cldr ) | ||
]); | ||
@@ -756,2 +829,3 @@ | ||
// 18: @symbolMap [Object] A bunch of other symbols. | ||
// 19: @nuDigitsMap [Array] Digits map if numbering system is different than `latn`. | ||
return properties; | ||
@@ -803,10 +877,2 @@ }; | ||
// ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions?redirectlocale=en-US&redirectslug=JavaScript%2FGuide%2FRegular_Expressions | ||
var regexpEscape = function( string ) { | ||
return string.replace( /([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1" ); | ||
}; | ||
/** | ||
@@ -824,4 +890,4 @@ * parse( value, properties ) | ||
var numberParse = function( value, properties ) { | ||
var aux, infinitySymbol, invertedSymbolMap, localizedSymbolsRe, negativePrefix, negativeSuffix, | ||
number, prefix, suffix; | ||
var aux, infinitySymbol, invertedNuDigitsMap, invertedSymbolMap, localizedDigitRe, | ||
localizedSymbolsRe, negativePrefix, negativeSuffix, number, prefix, suffix; | ||
@@ -832,2 +898,3 @@ infinitySymbol = properties[ 0 ]; | ||
negativeSuffix = properties[ 3 ]; | ||
invertedNuDigitsMap = properties[ 4 ]; | ||
@@ -844,2 +911,3 @@ // Infinite number. | ||
// TODO: Create it during setup, i.e., make it a property. | ||
localizedSymbolsRe = new RegExp( | ||
@@ -857,2 +925,17 @@ Object.keys( invertedSymbolMap ).map(function( localizedSymbol ) { | ||
// Reverse localized numbering system. | ||
if ( invertedNuDigitsMap ) { | ||
// TODO: Create it during setup, i.e., make it a property. | ||
localizedDigitRe = new RegExp( | ||
Object.keys( invertedNuDigitsMap ).map(function( localizedDigit ) { | ||
return regexpEscape( localizedDigit ); | ||
}).join( "|" ), | ||
"g" | ||
); | ||
value = value.replace( localizedDigitRe, function( localizedDigit ) { | ||
return invertedNuDigitsMap[ localizedDigit ]; | ||
}); | ||
} | ||
// Is it a valid number? | ||
@@ -965,3 +1048,4 @@ value = value.match( numberNumberRe ); | ||
var numberParseProperties = function( pattern, cldr ) { | ||
var negativePattern, negativeProperties; | ||
var invertedNuDigitsMap, invertedNuDigitsMapSanityCheck, negativePattern, negativeProperties, | ||
nuDigitsMap = numberNumberingSystemDigitsMap( cldr ); | ||
@@ -971,2 +1055,16 @@ pattern = pattern.split( ";" ); | ||
negativeProperties = numberPatternProperties( negativePattern ); | ||
if ( nuDigitsMap ) { | ||
invertedNuDigitsMap = nuDigitsMap.split( "" ).reduce(function( object, localizedDigit, i ) { | ||
object[ localizedDigit ] = String( i ); | ||
return object; | ||
}, {} ); | ||
invertedNuDigitsMapSanityCheck = "0123456789".split( "" ).reduce(function( object, digit ) { | ||
object[ digit ] = "invalid"; | ||
return object; | ||
}, {} ); | ||
invertedNuDigitsMap = objectFlatExtend( | ||
invertedNuDigitsMapSanityCheck, | ||
invertedNuDigitsMap | ||
); | ||
} | ||
@@ -981,2 +1079,4 @@ // 0: @infinitySymbol [String] Infinity symbol. | ||
// 3: @negativeSuffix [String] Negative suffix with percent or per mille stripped out. | ||
// 4: @invertedNuDigitsMap [Object] Inverted digits map if numbering system is different than | ||
// `latn` augmented with sanity check (similar to invertedSymbolMap). | ||
return [ | ||
@@ -986,3 +1086,4 @@ numberSymbol( "infinity", cldr ), | ||
negativeProperties[ 0 ], | ||
negativeProperties[ 10 ].replace( "%", "" ).replace( "\u2030", "" ) | ||
negativeProperties[ 10 ].replace( "%", "" ).replace( "\u2030", "" ), | ||
invertedNuDigitsMap | ||
]; | ||
@@ -989,0 +1090,0 @@ }; |
@@ -1,3 +0,3 @@ | ||
/*! | ||
* Globalize v1.0.0-alpha.10 | ||
/** | ||
* Globalize v1.0.0-alpha.11 | ||
* | ||
@@ -10,4 +10,8 @@ * http://github.com/jquery/globalize | ||
* | ||
* Date: 2014-10-22T17:24Z | ||
* Date: 2014-12-03T12:09Z | ||
*/ | ||
/*! | ||
* Globalize v1.0.0-alpha.11 2014-12-03T12:09Z Released under the MIT license | ||
* http://git.io/TrdQbw | ||
*/ | ||
(function( root, factory ) { | ||
@@ -22,3 +26,4 @@ | ||
"../globalize", | ||
"cldr/event" | ||
"cldr/event", | ||
"cldr/supplemental" | ||
], factory ); | ||
@@ -36,662 +41,174 @@ } else if ( typeof exports === "object" ) { | ||
var formatMessage = Globalize._formatMessage, | ||
validate = Globalize._validate, | ||
validateCldr = Globalize._validateCldr, | ||
var validateCldr = Globalize._validateCldr, | ||
validateDefaultLocale = Globalize._validateDefaultLocale, | ||
validateParameterPresence = Globalize._validateParameterPresence, | ||
validateParameterType = Globalize._validateParameterType, | ||
validateParameterTypePlainObject = Globalize._validateParameterTypePlainObject; | ||
validateParameterType = Globalize._validateParameterType; | ||
/** | ||
* parameterKeyPresence( value, name, key ) | ||
* make-plural.js -- https://github.com/eemeli/make-plural.js/ | ||
* Copyright (c) 2014 by Eemeli Aro <eemeli@gmail.com> | ||
* | ||
* @value [Object] Variable value. | ||
* Permission to use, copy, modify, and/or distribute this software for any | ||
* purpose with or without fee is hereby granted, provided that the above | ||
* copyright notice and this permission notice appear in all copies. | ||
* | ||
* @name [String] Name of variable. | ||
* | ||
* @key [String] The lowest valid value, inclusive. | ||
* The software is provided "as is" and the author disclaims all warranties | ||
* with regard to this software including all implied warranties of | ||
* merchantability and fitness. In no event shall the author be liable for | ||
* any special, direct, indirect, or consequential damages or any damages | ||
* whatsoever resulting from loss of use, data or profits, whether in an | ||
* action of contract, negligence or other tortious action, arising out of | ||
* or in connection with the use or performance of this software. | ||
*/ | ||
var validateParameterKeyPresence = function( value, name, key ) { | ||
validate( | ||
"E_PAR_MISSING_KEY", | ||
"Parameter `{name}` misses key `{key}`", | ||
value === undefined || key in value, | ||
{ | ||
key: key, | ||
name: "messageData" | ||
} | ||
); | ||
}; | ||
var MakePlural; | ||
/* jshint ignore:start */ | ||
MakePlural = (function() { | ||
var validateParameterTypeNumber = function( value, name ) { | ||
validateParameterType( | ||
value, | ||
name, | ||
value === undefined || typeof value === "number", | ||
"Number" | ||
); | ||
}; | ||
/** | ||
* cldrpluralparser.js | ||
* A parser engine for CLDR plural rules. | ||
* | ||
* Copyright 2012-2014 Santhosh Thottingal and other contributors | ||
* Released under the MIT license | ||
* http://opensource.org/licenses/MIT | ||
* | ||
* @source https://github.com/santhoshtr/CLDRPluralRuleParser | ||
* @author Santhosh Thottingal <santhosh.thottingal@gmail.com> | ||
* @author Timo Tijhof | ||
* @author Amir Aharoni | ||
*/ | ||
/** | ||
* Evaluates a plural rule in CLDR syntax for a number | ||
* @param {string} rule | ||
* @param {integer} number | ||
* @return {boolean} true if evaluation passed, false if evaluation failed. | ||
*/ | ||
// UMD returnExports https://github.com/umdjs/umd/blob/master/returnExports.js | ||
var CLDRPluralRuleParser = (function() { | ||
function pluralRuleParser(rule, number) { | ||
/* | ||
Syntax: see http://unicode.org/reports/tr35/#Language_Plural_Rules | ||
----------------------------------------------------------------- | ||
condition = and_condition ('or' and_condition)* | ||
('@integer' samples)? | ||
('@decimal' samples)? | ||
and_condition = relation ('and' relation)* | ||
relation = is_relation | in_relation | within_relation | ||
is_relation = expr 'is' ('not')? value | ||
in_relation = expr (('not')? 'in' | '=' | '!=') range_list | ||
within_relation = expr ('not')? 'within' range_list | ||
expr = operand (('mod' | '%') value)? | ||
operand = 'n' | 'i' | 'f' | 't' | 'v' | 'w' | ||
range_list = (range | value) (',' range_list)* | ||
value = digit+ | ||
digit = 0|1|2|3|4|5|6|7|8|9 | ||
range = value'..'value | ||
samples = sampleRange (',' sampleRange)* (',' ('…'|'...'))? | ||
sampleRange = decimalValue '~' decimalValue | ||
decimalValue = value ('.' value)? | ||
*/ | ||
// We don't evaluate the samples section of the rule. Ignore it. | ||
rule = rule.split('@')[0].replace(/^\s*/, '').replace(/\s*$/, ''); | ||
if (!rule.length) { | ||
// Empty rule or 'other' rule. | ||
return true; | ||
function parse(cond, symbols) { | ||
if (cond == 'i = 0 or n = 1') return 'n >= 0 && n <= 1'; | ||
if (cond == 'i = 0,1') return 'n >= 0 && n < 2'; | ||
if (cond == 'i = 1 and v = 0') { | ||
symbols['v0'] = 1; | ||
return 'n == 1 && v0'; | ||
} | ||
// Indicates the current position in the rule as we parse through it. | ||
// Shared among all parsing functions below. | ||
var pos = 0, | ||
operand, | ||
expression, | ||
relation, | ||
result, | ||
whitespace = makeRegexParser(/^\s+/), | ||
value = makeRegexParser(/^\d+/), | ||
_n_ = makeStringParser('n'), | ||
_i_ = makeStringParser('i'), | ||
_f_ = makeStringParser('f'), | ||
_t_ = makeStringParser('t'), | ||
_v_ = makeStringParser('v'), | ||
_w_ = makeStringParser('w'), | ||
_is_ = makeStringParser('is'), | ||
_isnot_ = makeStringParser('is not'), | ||
_isnot_sign_ = makeStringParser('!='), | ||
_equal_ = makeStringParser('='), | ||
_mod_ = makeStringParser('mod'), | ||
_percent_ = makeStringParser('%'), | ||
_not_ = makeStringParser('not'), | ||
_in_ = makeStringParser('in'), | ||
_within_ = makeStringParser('within'), | ||
_range_ = makeStringParser('..'), | ||
_comma_ = makeStringParser(','), | ||
_or_ = makeStringParser('or'), | ||
_and_ = makeStringParser('and'); | ||
function debug() { | ||
// console.log.apply(console, arguments); | ||
} | ||
debug('pluralRuleParser', rule, number); | ||
// Try parsers until one works, if none work return null | ||
function choice(parserSyntax) { | ||
return function() { | ||
var i, result; | ||
for (i = 0; i < parserSyntax.length; i++) { | ||
result = parserSyntax[i](); | ||
if (result !== null) { | ||
return result; | ||
} | ||
return cond | ||
.replace(/([tv]) (!?)= 0/g, function(m, sym, noteq) { | ||
var sn = sym + '0'; | ||
symbols[sn] = 1; | ||
return noteq ? '!' + sn : sn; | ||
}) | ||
.replace(/\b[fintv]\b/g, function(m) { | ||
symbols[m] = 1; | ||
return m; | ||
}) | ||
.replace(/([fin]) % (10+)/g, function(m, sym, num) { | ||
var sn = sym + num; | ||
symbols[sn] = 1; | ||
return sn; | ||
}) | ||
.replace(/n10+ = 0/g, 't0 && $&') | ||
.replace(/(\w+ (!?)= )([0-9.]+,[0-9.,]+)/g, function(m, se, noteq, x) { | ||
if (m == 'n = 0,1') return '(n == 0 || n == 1)'; | ||
if (noteq) return se + x.split(',').join(' && ' + se); | ||
return '(' + se + x.split(',').join(' || ' + se) + ')'; | ||
}) | ||
.replace(/(\w+) (!?)= ([0-9]+)\.\.([0-9]+)/g, function(m, sym, noteq, x0, x1) { | ||
if (Number(x0) + 1 == Number(x1)) { | ||
if (noteq) return sym + ' != ' + x0 + ' && ' + sym + ' != ' + x1; | ||
return '(' + sym + ' == ' + x0 + ' || ' + sym + ' == ' + x1 + ')'; | ||
} | ||
if (noteq) return '(' + sym + ' < ' + x0 + ' || ' + sym + ' > ' + x1 + ')'; | ||
if (sym == 'n') { symbols['t0'] = 1; return '(t0 && n >= ' + x0 + ' && n <= ' + x1 + ')'; } | ||
return '(' + sym + ' >= ' + x0 + ' && ' + sym + ' <= ' + x1 + ')'; | ||
}) | ||
.replace(/ and /g, ' && ') | ||
.replace(/ or /g, ' || ') | ||
.replace(/ = /g, ' == '); | ||
} | ||
return null; | ||
}; | ||
function vars(symbols) { | ||
var vars = []; | ||
if (symbols['i']) vars.push("i = s[0]"); | ||
if (symbols['f'] || symbols['v']) vars.push("f = s[1] || ''"); | ||
if (symbols['t']) vars.push("t = (s[1] || '').replace(/0+$/, '')"); | ||
if (symbols['v']) vars.push("v = f.length") | ||
if (symbols['v0']) vars.push("v0 = !s[1]"); | ||
if (symbols['t0'] || symbols['n10'] || symbols['n100']) vars.push("t0 = Number(s[0]) == n"); | ||
for (var k in symbols) if (/^.10+$/.test(k)) { | ||
var k0 = (k[0] == 'n') ? 't0 && s[0]' : k[0]; | ||
vars.push(k + ' = ' + k0 + '.substr(-' + k.substr(2).length + ')'); | ||
} | ||
// Try several parserSyntax-es in a row. | ||
// All must succeed; otherwise, return null. | ||
// This is the only eager one. | ||
function sequence(parserSyntax) { | ||
var i, parserRes, | ||
originalPos = pos, | ||
result = []; | ||
for (i = 0; i < parserSyntax.length; i++) { | ||
parserRes = parserSyntax[i](); | ||
if (parserRes === null) { | ||
pos = originalPos; | ||
return null; | ||
} | ||
result.push(parserRes); | ||
} | ||
return result; | ||
if (vars.length) { | ||
vars.unshift("s = String(n).split('.')"); | ||
return 'var ' + vars.join(', ') + ';'; | ||
} | ||
return ''; | ||
} | ||
// Run the same parser over and over until it fails. | ||
// Must succeed a minimum of n times; otherwise, return null. | ||
function nOrMore(n, p) { | ||
return function() { | ||
var originalPos = pos, | ||
result = [], | ||
parsed = p(); | ||
while (parsed !== null) { | ||
result.push(parsed); | ||
parsed = p(); | ||
} | ||
if (result.length < n) { | ||
pos = originalPos; | ||
return null; | ||
} | ||
return result; | ||
}; | ||
} | ||
// Helpers - just make parserSyntax out of simpler JS builtin types | ||
function makeStringParser(s) { | ||
var len = s.length; | ||
return function() { | ||
var result = null; | ||
if (rule.substr(pos, len) === s) { | ||
result = s; | ||
pos += len; | ||
} | ||
return result; | ||
}; | ||
} | ||
function makeRegexParser(regex) { | ||
return function() { | ||
var matches = rule.substr(pos).match(regex); | ||
if (matches === null) { | ||
return null; | ||
} | ||
pos += matches[0].length; | ||
return matches[0]; | ||
}; | ||
} | ||
/** | ||
* Integer digits of n. | ||
*/ | ||
function i() { | ||
var result = _i_(); | ||
if (result === null) { | ||
debug(' -- failed i', parseInt(number, 10)); | ||
return result; | ||
} | ||
result = parseInt(number, 10); | ||
debug(' -- passed i ', result); | ||
return result; | ||
} | ||
/** | ||
* Absolute value of the source number (integer and decimals). | ||
*/ | ||
function n() { | ||
var result = _n_(); | ||
if (result === null) { | ||
debug(' -- failed n ', number); | ||
return result; | ||
} | ||
result = parseFloat(number, 10); | ||
debug(' -- passed n ', result); | ||
return result; | ||
} | ||
/** | ||
* Visible fractional digits in n, with trailing zeros. | ||
*/ | ||
function f() { | ||
var result = _f_(); | ||
if (result === null) { | ||
debug(' -- failed f ', number); | ||
return result; | ||
} | ||
result = (number + '.').split('.')[1] || 0; | ||
debug(' -- passed f ', result); | ||
return result; | ||
} | ||
/** | ||
* Visible fractional digits in n, without trailing zeros. | ||
*/ | ||
function t() { | ||
var result = _t_(); | ||
if (result === null) { | ||
debug(' -- failed t ', number); | ||
return result; | ||
} | ||
result = (number + '.').split('.')[1].replace(/0$/, '') || 0; | ||
debug(' -- passed t ', result); | ||
return result; | ||
} | ||
/** | ||
* Number of visible fraction digits in n, with trailing zeros. | ||
*/ | ||
function v() { | ||
var result = _v_(); | ||
if (result === null) { | ||
debug(' -- failed v ', number); | ||
return result; | ||
} | ||
result = (number + '.').split('.')[1].length || 0; | ||
debug(' -- passed v ', result); | ||
return result; | ||
} | ||
/** | ||
* Number of visible fraction digits in n, without trailing zeros. | ||
*/ | ||
function w() { | ||
var result = _w_(); | ||
if (result === null) { | ||
debug(' -- failed w ', number); | ||
return result; | ||
} | ||
result = (number + '.').split('.')[1].replace(/0$/, '').length || 0; | ||
debug(' -- passed w ', result); | ||
return result; | ||
} | ||
// operand = 'n' | 'i' | 'f' | 't' | 'v' | 'w' | ||
operand = choice([n, i, f, t, v, w]); | ||
// expr = operand (('mod' | '%') value)? | ||
expression = choice([mod, operand]); | ||
function mod() { | ||
var result = sequence( | ||
[operand, whitespace, choice([_mod_, _percent_]), whitespace, value] | ||
); | ||
if (result === null) { | ||
debug(' -- failed mod'); | ||
return null; | ||
} | ||
debug(' -- passed ' + parseInt(result[0], 10) + ' ' + result[2] + ' ' + parseInt(result[4], 10)); | ||
return parseFloat(result[0]) % parseInt(result[4], 10); | ||
} | ||
function not() { | ||
var result = sequence([whitespace, _not_]); | ||
if (result === null) { | ||
debug(' -- failed not'); | ||
return null; | ||
} | ||
return result[1]; | ||
} | ||
// is_relation = expr 'is' ('not')? value | ||
function is() { | ||
var result = sequence([expression, whitespace, choice([_is_]), whitespace, value]); | ||
if (result !== null) { | ||
debug(' -- passed is : ' + result[0] + ' == ' + parseInt(result[4], 10)); | ||
return result[0] === parseInt(result[4], 10); | ||
} | ||
debug(' -- failed is'); | ||
return null; | ||
} | ||
// is_relation = expr 'is' ('not')? value | ||
function isnot() { | ||
var result = sequence( | ||
[expression, whitespace, choice([_isnot_, _isnot_sign_]), whitespace, value] | ||
); | ||
if (result !== null) { | ||
debug(' -- passed isnot: ' + result[0] + ' != ' + parseInt(result[4], 10)); | ||
return result[0] !== parseInt(result[4], 10); | ||
} | ||
debug(' -- failed isnot'); | ||
return null; | ||
} | ||
function not_in() { | ||
var i, range_list, | ||
result = sequence([expression, whitespace, _isnot_sign_, whitespace, rangeList]); | ||
if (result !== null) { | ||
debug(' -- passed not_in: ' + result[0] + ' != ' + result[4]); | ||
range_list = result[4]; | ||
for (i = 0; i < range_list.length; i++) { | ||
if (parseInt(range_list[i], 10) === parseInt(result[0], 10)) { | ||
return false; | ||
function build(lc, opt, tests) { | ||
var lines = [], symbols = {}, | ||
_fold = function(l) { return l.replace(/(.{1,72})( \|\| |$) ?/gm, '$1\n $2').replace(/\s+$/gm, ''); }, | ||
_compile = function(type, req) { | ||
var cases = []; | ||
if (MakePlural.rules[type][lc]) { | ||
for (var r in MakePlural.rules[type][lc]) { | ||
var key = r.replace('pluralRule-count-', ''), | ||
parts = MakePlural.rules[type][lc][r].split(/@\w*/), | ||
cond = parts.shift().trim(); | ||
if (cond) cases.push([parse(cond, symbols), key]); | ||
tests[type][key] = parts.join(' ') | ||
.replace(/^[ ,]+|[ ,…]+$/g, '') | ||
.replace(/(0\.[0-9])~(1\.[1-9])/g, '$1 1.0 $2') | ||
.split(/[ ,~…]+/); | ||
} | ||
} | ||
return true; | ||
} | ||
debug(' -- failed not_in'); | ||
return null; | ||
} | ||
// range_list = (range | value) (',' range_list)* | ||
function rangeList() { | ||
var result = sequence([choice([range, value]), nOrMore(0, rangeTail)]), | ||
resultList = []; | ||
if (result !== null) { | ||
resultList = resultList.concat(result[0]); | ||
if (result[1][0]) { | ||
resultList = resultList.concat(result[1][0]); | ||
} | ||
return resultList; | ||
} | ||
debug(' -- failed rangeList'); | ||
return null; | ||
} | ||
function rangeTail() { | ||
// ',' range_list | ||
var result = sequence([_comma_, rangeList]); | ||
if (result !== null) { | ||
return result[1]; | ||
} | ||
debug(' -- failed rangeTail'); | ||
return null; | ||
} | ||
// range = value'..'value | ||
function range() { | ||
var i, array, left, right, | ||
result = sequence([value, _range_, value]); | ||
if (result !== null) { | ||
debug(' -- passed range'); | ||
array = []; | ||
left = parseInt(result[0], 10); | ||
right = parseInt(result[2], 10); | ||
for (i = left; i <= right; i++) { | ||
array.push(i); | ||
} | ||
return array; | ||
} | ||
debug(' -- failed range'); | ||
return null; | ||
} | ||
function _in() { | ||
var result, range_list, i; | ||
// in_relation = expr ('not')? 'in' range_list | ||
result = sequence( | ||
[expression, nOrMore(0, not), whitespace, choice([_in_, _equal_]), whitespace, rangeList] | ||
); | ||
if (result !== null) { | ||
debug(' -- passed _in:' + result); | ||
range_list = result[5]; | ||
for (i = 0; i < range_list.length; i++) { | ||
if (parseInt(range_list[i], 10) === parseFloat(result[0])) { | ||
return (result[1][0] !== 'not'); | ||
} | ||
} | ||
return (result[1][0] === 'not'); | ||
} | ||
debug(' -- failed _in '); | ||
return null; | ||
} | ||
/** | ||
* The difference between "in" and "within" is that | ||
* "in" only includes integers in the specified range, | ||
* while "within" includes all values. | ||
*/ | ||
function within() { | ||
var range_list, result; | ||
// within_relation = expr ('not')? 'within' range_list | ||
result = sequence( | ||
[expression, nOrMore(0, not), whitespace, _within_, whitespace, rangeList] | ||
); | ||
if (result !== null) { | ||
debug(' -- passed within'); | ||
range_list = result[5]; | ||
if ((result[0] >= parseInt(range_list[0], 10)) && | ||
(result[0] < parseInt(range_list[range_list.length - 1], 10))) { | ||
return (result[1][0] !== 'not'); | ||
} | ||
return (result[1][0] === 'not'); | ||
} | ||
debug(' -- failed within '); | ||
return null; | ||
} | ||
// relation = is_relation | in_relation | within_relation | ||
relation = choice([is, not_in, isnot, _in, within]); | ||
// and_condition = relation ('and' relation)* | ||
function and() { | ||
var i, | ||
result = sequence([relation, nOrMore(0, andTail)]); | ||
if (result) { | ||
if (!result[0]) { | ||
} else if (req) { | ||
if (!opt['quiet']) console.error('Locale "' + lc + '" ' + type + ' rules not found'); | ||
return false; | ||
} | ||
if (!cases.length) return "'other'"; | ||
if (cases.length == 1) return "(" + cases[0][0] + ") ? '" + cases[0][1] + "' : 'other'"; | ||
return cases.map(function(c) { return "(" + c[0] + ") ? '" + c[1] + "'"; }).concat("'other'").join('\n : '); | ||
}; | ||
for (i = 0; i < result[1].length; i++) { | ||
if (!result[1][i]) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
if (opt['ordinals']) { | ||
if (opt['no_cardinals']) { | ||
var l = _compile('ordinal', true); | ||
if (!l) return null; | ||
lines.push(_fold(' return ' + l + ';')); | ||
} else { | ||
lines.push(_fold(' if (ord) return ' + _compile('ordinal', false) + ';')); | ||
} | ||
debug(' -- failed and'); | ||
return null; | ||
} | ||
// ('and' relation)* | ||
function andTail() { | ||
var result = sequence([whitespace, _and_, whitespace, relation]); | ||
if (result !== null) { | ||
debug(' -- passed andTail' + result); | ||
return result[3]; | ||
} | ||
debug(' -- failed andTail'); | ||
return null; | ||
if (!opt['no_cardinals']) { | ||
var l = _compile('cardinal', true); | ||
if (!l) return null; | ||
lines.push(_fold(' return ' + l + ';')); | ||
} | ||
// ('or' and_condition)* | ||
function orTail() { | ||
var result = sequence([whitespace, _or_, whitespace, and]); | ||
var fn_vars = vars(symbols).replace(/(.{1,78})(,|$) ?/g, '\n $1$2').trim(); | ||
if (fn_vars) lines.unshift(' ' + fn_vars); | ||
return lines.join('\n'); | ||
} | ||
if (result !== null) { | ||
debug(' -- passed orTail: ' + result[3]); | ||
return result[3]; | ||
} | ||
debug(' -- failed orTail'); | ||
return null; | ||
} | ||
// condition = and_condition ('or' and_condition)* | ||
function condition() { | ||
var i, | ||
result = sequence([and, nOrMore(0, orTail)]); | ||
if (result) { | ||
for (i = 0; i < result[1].length; i++) { | ||
if (result[1][i]) { | ||
return true; | ||
} | ||
} | ||
return result[0]; | ||
} | ||
return false; | ||
var MakePlural = function(lc, opt) { | ||
if (typeof lc == 'object') { opt = lc; lc = opt.lc; } | ||
else { | ||
if (!opt) opt = MakePlural.opt; | ||
if (!lc) lc = opt.lc; | ||
} | ||
var tests = { 'ordinal':{}, 'cardinal':{} }, | ||
fn_body = build(lc, opt, tests), | ||
fn = opt['ordinals'] && !opt['no_cardinals'] | ||
? new Function('n', 'ord', fn_body) | ||
: new Function('n', fn_body); | ||
fn.toString = function(name) { | ||
var s = Function.prototype.toString.call(fn); | ||
return s.replace(/^function( \w+)?/, name ? 'function ' + name : 'function'); | ||
}; | ||
return fn_body && (opt['no_tests'] || test(lc, fn, tests, opt)) ? fn : null; | ||
}; | ||
result = condition(); | ||
MakePlural.opt = {}; | ||
MakePlural.rules = {}; | ||
/** | ||
* For success, the pos must have gotten to the end of the rule | ||
* and returned a non-null. | ||
* n.b. This is part of language infrastructure, | ||
* so we do not throw an internationalizable message. | ||
*/ | ||
if (result === null) { | ||
throw new Error('Parse error at position ' + pos.toString() + ' for rule: ' + rule); | ||
} | ||
if (pos !== rule.length) { | ||
debug('Warning: Rule not parsed completely. Parser stopped at ' + rule.substr(0, pos) + ' for rule: ' + rule); | ||
} | ||
return result; | ||
} | ||
return pluralRuleParser; | ||
return MakePlural; | ||
}()); | ||
/* jshint ignore:end */ | ||
/** | ||
* pluralForm( value, cldr ) | ||
* | ||
* @value [Number] | ||
* | ||
* @cldr [Cldr instance]. | ||
* | ||
* Return the corresponding form (zero | one | two | few | many | other) of a | ||
* value given locale @cldr. | ||
*/ | ||
var pluralForm = function( value, cldr ) { | ||
var form, | ||
rules = cldr.supplemental( "plurals-type-cardinal/{language}" ); | ||
for ( form in rules ) { | ||
if ( CLDRPluralRuleParser( rules[ form ], value ) ) { | ||
return form.replace( /pluralRule-count-/, "" ); | ||
} | ||
} | ||
return null; | ||
var validateParameterTypeNumber = function( value, name ) { | ||
validateParameterType( | ||
value, | ||
name, | ||
value === undefined || typeof value === "number", | ||
"Number" | ||
); | ||
}; | ||
@@ -703,56 +220,32 @@ | ||
/** | ||
* .formatPlural( value, data, formatValue ) | ||
* .plural( value ) | ||
* | ||
* @value [Number] | ||
* | ||
* @messageData [JSON] eg. { one: "{0} second", other: "{0} seconds" } | ||
* | ||
* @formatValue [String|Number] It defaults to `value`. It's used to replace the | ||
* {0} variable of plural messages. | ||
* | ||
* Return the appropriate message based on value's plural group: zero | one | | ||
* two | few | many | other. | ||
* Return the corresponding form (zero | one | two | few | many | other) of a | ||
* value given locale. | ||
*/ | ||
Globalize.formatPlural = | ||
Globalize.prototype.formatPlural = function( value, messageData, formatValue ) { | ||
var form; | ||
// Note: validateParameterTypeNumber( value, "value" ) is deferred to this.plural(). | ||
Globalize.plural = | ||
Globalize.prototype.plural = function( value ) { | ||
validateParameterPresence( value, "value" ); | ||
validateParameterPresence( messageData, "messageData" ); | ||
validateParameterTypePlainObject( messageData, "messageData" ); | ||
validateParameterType( | ||
formatValue, | ||
"formatValue", | ||
formatValue === undefined || typeof formatValue === "string" || | ||
typeof formatValue === "number", | ||
"String or Number" | ||
); | ||
form = this.plural( value ); | ||
// formatValue defaults to value, but it accepts anything including empty strings. | ||
formatValue = formatValue === undefined ? value : formatValue; | ||
validateParameterKeyPresence( messageData, "messageData", form ); | ||
return formatMessage( messageData[ form ], [ formatValue ] ); | ||
validateParameterTypeNumber( value, "value" ); | ||
return this.pluralGenerator()( value ); | ||
}; | ||
/** | ||
* .plural( value ) | ||
* .pluralGenerator() | ||
* | ||
* Return a plural function (of the form below). | ||
* | ||
* fn( value ) | ||
* | ||
* @value [Number] | ||
* | ||
* Return the corresponding form (zero | one | two | few | many | other) of a | ||
* value given locale. | ||
* Return the corresponding form (zero | one | two | few | many | other) of a value given the | ||
* default/instance locale. | ||
*/ | ||
Globalize.plural = | ||
Globalize.prototype.plural = function( value ) { | ||
var cldr, form; | ||
Globalize.pluralGenerator = | ||
Globalize.prototype.pluralGenerator = function() { | ||
var cldr, plural; | ||
validateParameterPresence( value, "value" ); | ||
validateParameterTypeNumber( value, "value" ); | ||
cldr = this.cldr; | ||
@@ -763,10 +256,18 @@ | ||
cldr.on( "get", validateCldr ); | ||
form = pluralForm( value, cldr ); | ||
cldr.supplemental( "plurals-type-cardinal/{language}" ); | ||
cldr.off( "get", validateCldr ); | ||
validate( "E_INVALID_CLDR", "{description}", typeof form === "string", { | ||
description: "Missing rules to deduce plural form of `" + value + "`" | ||
}); | ||
// Set CLDR data | ||
MakePlural.rules = { | ||
cardinal: cldr.supplemental( "plurals-type-cardinal" ) | ||
}; | ||
return form; | ||
plural = MakePlural( cldr.attributes.language, { "no_tests": true } ); | ||
return function( value ) { | ||
validateParameterPresence( value, "value" ); | ||
validateParameterTypeNumber( value, "value" ); | ||
return plural( value ); | ||
}; | ||
}; | ||
@@ -773,0 +274,0 @@ |
/*! | ||
* Globalize v1.0.0-alpha.10 | ||
* Globalize v1.0.0-alpha.11 | ||
* | ||
@@ -10,3 +10,3 @@ * http://github.com/jquery/globalize | ||
* | ||
* Date: 2014-10-22T17:24Z | ||
* Date: 2014-12-03T12:09Z | ||
*/ | ||
@@ -13,0 +13,0 @@ |
@@ -33,6 +33,8 @@ ## .formatNumber( value [, options] ) | ||
var ar = new Globalize( "ar" ), | ||
es = new Globalize( "es" ); | ||
es = new Globalize( "es" ), | ||
zh = new Globalize( "zh-u-nu-native" ); | ||
ar.formatNumber( 3.141592 ); // "3٫142" | ||
ar.formatNumber( 3.141592 ); // "٣٫١٤٢" | ||
es.formatNumber( 3.141592 ); // "3,142" | ||
zh.formatNumber( 3.141592 ); // "三.一四二" | ||
``` | ||
@@ -39,0 +41,0 @@ |
@@ -64,6 +64,8 @@ ## .numberFormatter( [options] ) | ||
var arFormatter = Globalize( "ar" ).numberFormatter(), | ||
esFormatter = Globalize( "es" ).numberFormatter(); | ||
esFormatter = Globalize( "es" ).numberFormatter(), | ||
zhFormatter = Globalize( "zh-u-nu-native" ).numberFormatter(); | ||
arFormatter( 3.141592 ); // "3٫142" | ||
arFormatter( 3.141592 ); // "٣٫١٤٢" | ||
esFormatter( 3.141592 ); // "3,142" | ||
zhFormatter( 3.141592 ); // "三.一四二" | ||
``` | ||
@@ -70,0 +72,0 @@ |
@@ -15,4 +15,4 @@ ## .plural( value ) | ||
See also its sibling method [`.formatPlural( value, messageData [, formatValue ])` | ||
](./format-plural.md). | ||
*Important*: Use [`.pluralGenerator()`](./plural-generator.md) instead when | ||
using this function two or more times, for improved performance. | ||
@@ -49,3 +49,3 @@ ### Parameters | ||
zh.formatPlural( 1 ); // "other" | ||
zh.plural( 1 ); // "other" | ||
``` |
@@ -77,3 +77,3 @@ module.exports = function( grunt ) { | ||
dist: { | ||
src: [ "dist/globalize*.js", "dist/globalize/*.js", "!dist/**/*.min.*js" ], | ||
src: [ "dist/globalize*.js", "dist/globalize/*.js" ], | ||
options: { | ||
@@ -88,3 +88,3 @@ jshintrc: "src/.dist-jshintrc" | ||
test: [ "test/*.js", "test/functional/**/*.js", "test/unit/**/*.js" ], | ||
dist: [ "dist/globalize*.js", "dist/globalize/*.js", "!dist/**/*.min.*js" ] | ||
dist: [ "dist/globalize*.js", "dist/globalize/*.js" ] | ||
}, | ||
@@ -111,4 +111,3 @@ qunit: { | ||
cldr: "../external/cldrjs/dist/cldr", | ||
CLDRPluralRuleParser: "../external/CLDRPluralRuleParser/src/" + | ||
"CLDRPluralRuleParser" | ||
"make-plural": "../external/make-plural/make-plural" | ||
}, | ||
@@ -136,2 +135,30 @@ skipSemiColonInsertion: true, | ||
.replace( /}\)\);\s+$/, "}());" ); | ||
// MakePlural | ||
} else if ( (/make-plural/).test( id ) ) { | ||
return contents | ||
// Replace its wrapper into var assignment. | ||
.replace( /\(function \(global\) {/, [ | ||
"var MakePlural;", | ||
"/* jshint ignore:start */", | ||
"MakePlural = (function() {" | ||
].join( "\n" ) ) | ||
.replace( /if \(\(typeof module !== 'undefined'[\s\S]*/, [ | ||
"return MakePlural;", | ||
"}());", | ||
"/* jshint ignore:end */" | ||
].join( "\n" ) ) | ||
// Remove if (!MakePlural.rules...) {...} | ||
.replace( /if \(!MakePlural.rules \|\|[\s\S]*?}/, "" ) | ||
// Remove function xhr_require(src, url) {...} | ||
.replace( /function xhr_require\(src, [\s\S]*?}/, "" ) | ||
// Remove function test(...) {...} | ||
.replace( /function test\(lc, fn, [\s\S]*?return ok;\n}/, "" ) | ||
// Remove MakePlural.load = function(.*) {...return MakePlural;.*}; | ||
.replace( /MakePlural.load = function\([\s\S]*?return MakePlural;\n};/, "" ); | ||
} | ||
@@ -201,3 +228,3 @@ | ||
include: [ "plural" ], | ||
exclude: [ "cldr", "cldr/event", "./core" ], | ||
exclude: [ "cldr", "cldr/event", "cldr/supplemental", "./core" ], | ||
create: true, | ||
@@ -268,7 +295,7 @@ override: { | ||
files: { | ||
"dist/globalize.min.js": [ "dist/globalize.js" ], | ||
"dist/globalize/date.min.js": [ "dist/globalize/date.js" ], | ||
"dist/globalize/number.min.js": [ "dist/globalize/number.js" ], | ||
"dist/globalize/plural.min.js": [ "dist/globalize/plural.js" ], | ||
"dist/globalize/message.min.js": [ "dist/globalize/message.js" ] | ||
"tmp/globalize.min.js": [ "dist/globalize.js" ], | ||
"tmp/globalize/date.min.js": [ "dist/globalize/date.js" ], | ||
"tmp/globalize/number.min.js": [ "dist/globalize/number.js" ], | ||
"tmp/globalize/plural.min.js": [ "dist/globalize/plural.js" ], | ||
"tmp/globalize/message.min.js": [ "dist/globalize/message.js" ] | ||
} | ||
@@ -281,4 +308,4 @@ } | ||
files: [ | ||
"dist/globalize.min.js", | ||
"dist/globalize/*min.js" | ||
"tmp/globalize.min.js", | ||
"tmp/globalize/*min.js" | ||
], | ||
@@ -285,0 +312,0 @@ options: { |
{ | ||
"name": "globalize", | ||
"version": "1.0.0-alpha.10", | ||
"version": "1.0.0-alpha.11", | ||
"description": "A JavaScript library for internationalization and localization that leverage the official Unicode CLDR JSON data.", | ||
@@ -67,3 +67,3 @@ "keywords": [ | ||
"dependencies": { | ||
"cldrjs": "0.3.9" | ||
"cldrjs": "0.3.10" | ||
}, | ||
@@ -74,3 +74,3 @@ "peerDependencies": { | ||
"devDependencies": { | ||
"cldr-data-downloader": "0.0.x", | ||
"cldr-data-downloader": "0.1.x", | ||
"grunt": "0.4.5", | ||
@@ -77,0 +77,0 @@ "grunt-check-dependencies": "0.6.0", |
@@ -103,3 +103,3 @@ # Globalize | ||
| globalize/number.js | +2.6KB | [Number module](#number_module) provides number formatting and parsing | | ||
| globalize/plural.js | +2.0KB | [Plural module](#plural_module) provides pluralization support | | ||
| globalize/plural.js | +1.7KB | [Plural module](#plural_module) provides pluralization support | | ||
<!--- By updating this table, also update its clone in #usage --> | ||
@@ -172,3 +172,3 @@ | ||
| Date module | cldr/main/`locale`/ca-gregorian.json<br>cldr/main/`locale`/timeZoneNames.json<br>cldr/supplemental/timeData.json<br>cldr/supplemental/weekData.json | | ||
| Number module | cldr/main/`locale`/numbers.json | | ||
| Number module | cldr/main/`locale`/numbers.json<br>cldr/supplemental/numberingSystems.json | | ||
| Plural module | cldr/supplemental/plurals.json | | ||
@@ -319,10 +319,10 @@ | ||
- **`Globalize.formatPlural( value, messageData [, formatValue ] )`** | ||
- **`.pluralGenerator()`** | ||
Return the appropriate message based on value's plural group: `zero`, `one`, | ||
`two`, `few`, `many`, or `other`. | ||
Return a function that returns the value's corresponding plural group: `zero`, `one`, `two`, `few`, | ||
`many`, or `other`. | ||
[Read more...](doc/api/plural/format-plural.md) | ||
[Read more...](doc/api/plural/plural-generator.md) | ||
- **`Globalize.plural( value )`** | ||
- **`.plural( value )`** | ||
@@ -372,8 +372,2 @@ Return the value's corresponding plural group: `zero`, `one`, `two`, `few`, `many`, or `other`. | ||
- **`E_PAR_MISSING_KEY`** | ||
Thrown when a parameter misses a required key. | ||
[Read more...](doc/error/e-par-missing-key.md) | ||
- **`E_PAR_OUT_OF_RANGE`** | ||
@@ -380,0 +374,0 @@ |
@@ -1,2 +0,2 @@ | ||
/*! | ||
/** | ||
* Globalize v@VERSION | ||
@@ -12,2 +12,6 @@ * | ||
*/ | ||
/*! | ||
* Globalize v@VERSION @DATE Released under the MIT license | ||
* http://git.io/TrdQbw | ||
*/ | ||
(function( root, factory ) { | ||
@@ -14,0 +18,0 @@ |
@@ -1,2 +0,2 @@ | ||
/*! | ||
/** | ||
* Globalize v@VERSION | ||
@@ -12,2 +12,6 @@ * | ||
*/ | ||
/*! | ||
* Globalize v@VERSION @DATE Released under the MIT license | ||
* http://git.io/TrdQbw | ||
*/ | ||
(function( root, factory ) { | ||
@@ -39,2 +43,3 @@ | ||
isPlainObject = Globalize._isPlainObject, | ||
regexpEscape = Globalize._regexpEscape, | ||
validateCldr = Globalize._validateCldr, | ||
@@ -41,0 +46,0 @@ validateDefaultLocale = Globalize._validateDefaultLocale, |
@@ -1,2 +0,2 @@ | ||
/*! | ||
/** | ||
* Globalize v@VERSION | ||
@@ -12,2 +12,6 @@ * | ||
*/ | ||
/*! | ||
* Globalize v@VERSION @DATE Released under the MIT license | ||
* http://git.io/TrdQbw | ||
*/ | ||
(function( root, factory ) { | ||
@@ -14,0 +18,0 @@ |
@@ -1,2 +0,2 @@ | ||
/*! | ||
/** | ||
* Globalize v@VERSION | ||
@@ -12,2 +12,6 @@ * | ||
*/ | ||
/*! | ||
* Globalize v@VERSION @DATE Released under the MIT license | ||
* http://git.io/TrdQbw | ||
*/ | ||
(function( root, factory ) { | ||
@@ -22,3 +26,4 @@ | ||
"../globalize", | ||
"cldr/event" | ||
"cldr/event", | ||
"cldr/supplemental" | ||
], factory ); | ||
@@ -37,2 +42,3 @@ } else if ( typeof exports === "object" ) { | ||
var createError = Globalize._createError, | ||
regexpEscape = Globalize._regexpEscape, | ||
validateCldr = Globalize._validateCldr, | ||
@@ -39,0 +45,0 @@ validateDefaultLocale = Globalize._validateDefaultLocale, |
@@ -1,2 +0,2 @@ | ||
/*! | ||
/** | ||
* Globalize v@VERSION | ||
@@ -12,2 +12,6 @@ * | ||
*/ | ||
/*! | ||
* Globalize v@VERSION @DATE Released under the MIT license | ||
* http://git.io/TrdQbw | ||
*/ | ||
(function( root, factory ) { | ||
@@ -22,3 +26,4 @@ | ||
"../globalize", | ||
"cldr/event" | ||
"cldr/event", | ||
"cldr/supplemental" | ||
], factory ); | ||
@@ -36,8 +41,5 @@ } else if ( typeof exports === "object" ) { | ||
var formatMessage = Globalize._formatMessage, | ||
validate = Globalize._validate, | ||
validateCldr = Globalize._validateCldr, | ||
var validateCldr = Globalize._validateCldr, | ||
validateDefaultLocale = Globalize._validateDefaultLocale, | ||
validateParameterPresence = Globalize._validateParameterPresence, | ||
validateParameterType = Globalize._validateParameterType, | ||
validateParameterTypePlainObject = Globalize._validateParameterTypePlainObject; | ||
validateParameterType = Globalize._validateParameterType; |
@@ -16,2 +16,3 @@ define([ | ||
"./util/is-plain-object", | ||
"./util/regexp/escape", | ||
"cldr/event" | ||
@@ -21,3 +22,3 @@ ], function( Cldr, createError, formatMessage, validate, validateCldr, validateDefaultLocale, | ||
validateParameterTypeLocale, validateParameterTypePlainObject, alwaysArray, alwaysCldr, | ||
isPlainObject ) { | ||
isPlainObject, regexpEscape ) { | ||
@@ -92,3 +93,3 @@ function validateLikelySubtags( cldr ) { | ||
Globalize._isPlainObject = isPlainObject; | ||
Globalize._validate = validate; | ||
Globalize._regexpEscape = regexpEscape; | ||
Globalize._validateCldr = validateCldr; | ||
@@ -100,2 +101,3 @@ Globalize._validateDefaultLocale = validateDefaultLocale; | ||
Globalize._validateParameterType = validateParameterType; | ||
Globalize._validate = validate; | ||
@@ -102,0 +104,0 @@ return Globalize; |
@@ -247,3 +247,11 @@ define([ | ||
// Anything else is considered a literal, including [ ,:/.'@#], chinese, japonese, and | ||
// ' literals. | ||
case "'": | ||
current = current.replace( /''/, "'" ); | ||
if ( length > 2 ) { | ||
current = current.slice( 1, -1 ); | ||
} | ||
return current; | ||
// Anything else is considered a literal, including [ ,:/.@#], chinese, japonese, and | ||
// arabic characters. | ||
@@ -250,0 +258,0 @@ default: |
define(function() { | ||
return (/([a-z])\1*|'[^']+'|''|./ig); | ||
return (/([a-z])\1*|'([^']|'')+'|''|./ig); | ||
}); |
define([ | ||
"./pattern-re" | ||
], function( datePatternRe ) { | ||
"./pattern-re", | ||
"../util/regexp/escape" | ||
], function( datePatternRe, regexpEscape ) { | ||
@@ -315,7 +316,7 @@ /** | ||
token.type = "literal"; | ||
if ( current.charAt( 1 ) === "'" ) { | ||
tokenRe = /'/; | ||
} else { | ||
tokenRe = /'[^']+'/; | ||
current = current.replace( /''/, "'" ); | ||
if ( length > 2 ) { | ||
current = current.slice( 1, -1 ); | ||
} | ||
tokenRe = new RegExp( regexpEscape( current ) ); | ||
break; | ||
@@ -322,0 +323,0 @@ |
define([ | ||
"./numbering-system-digits-map", | ||
"./pattern-properties", | ||
@@ -7,3 +8,3 @@ "./symbol", | ||
"../util/number/round" | ||
], function( numberPatternProperties, numberSymbol, numberSymbolMap, | ||
], function( numberNumberingSystemDigitsMap, numberPatternProperties, numberSymbol, numberSymbolMap, | ||
numberSymbolName, numberRound ) { | ||
@@ -56,3 +57,4 @@ | ||
numberSymbol( "nan", cldr ), | ||
numberSymbolMap( cldr ) | ||
numberSymbolMap( cldr ), | ||
numberNumberingSystemDigitsMap( cldr ) | ||
]); | ||
@@ -92,2 +94,3 @@ | ||
// 18: @symbolMap [Object] A bunch of other symbols. | ||
// 19: @nuDigitsMap [Array] Digits map if numbering system is different than `latn`. | ||
return properties; | ||
@@ -94,0 +97,0 @@ }; |
@@ -20,3 +20,3 @@ define([ | ||
var infinitySymbol, maximumFractionDigits, maximumSignificantDigits, minimumFractionDigits, | ||
minimumIntegerDigits, minimumSignificantDigits, nanSymbol, padding, prefix, | ||
minimumIntegerDigits, minimumSignificantDigits, nanSymbol, nuDigitsMap, padding, prefix, | ||
primaryGroupingSize, pattern, ret, round, roundIncrement, secondaryGroupingSize, suffix, | ||
@@ -38,2 +38,3 @@ symbolMap; | ||
symbolMap = properties[ 18 ]; | ||
nuDigitsMap = properties[ 19 ]; | ||
@@ -96,3 +97,3 @@ // NaN | ||
// Padding | ||
// Padding/'([^']|'')+'|''|[.,\-+E%\u2030]/g | ||
// TODO implement here | ||
@@ -102,8 +103,26 @@ | ||
// Symbols | ||
return ret.replace( /'[^']+'|[.,\-+E%\u2030]/g, function( symbol ) { | ||
if ( symbol.charAt( 0 ) === "'" ) { | ||
return symbol; | ||
return ret.replace( /('([^']|'')+'|'')|./g, function( character, literal ) { | ||
// Literals | ||
if ( literal ) { | ||
literal = literal.replace( /''/, "'" ); | ||
if ( literal.length > 2 ) { | ||
literal = literal.slice( 1, -1 ); | ||
} | ||
return literal; | ||
} | ||
return symbolMap[ symbol ]; | ||
// Symbols | ||
character = character.replace( /[.,\-+E%\u2030]/, function( symbol ) { | ||
return symbolMap[ symbol ]; | ||
}); | ||
// Numbering system | ||
if ( nuDigitsMap ) { | ||
character = character.replace( /[0-9]/, function( digit ) { | ||
return nuDigitsMap[ +digit ]; | ||
}); | ||
} | ||
return character; | ||
}); | ||
@@ -110,0 +129,0 @@ }; |
@@ -6,5 +6,25 @@ define(function() { | ||
* | ||
* TODO support ( native | traditional | finance ). | ||
* - http://www.unicode.org/reports/tr35/tr35-numbers.html#otherNumberingSystems | ||
* - http://cldr.unicode.org/index/bcp47-extension | ||
* - http://www.unicode.org/reports/tr35/#u_Extension | ||
*/ | ||
return function( cldr ) { | ||
var nu = cldr.attributes[ "u-nu" ]; | ||
if ( nu ) { | ||
if ( nu === "traditio" ) { | ||
nu = "traditional"; | ||
} | ||
if ( [ "native", "traditional", "finance" ].indexOf( nu ) !== -1 ) { | ||
// Unicode locale extension `u-nu` is set using either (native, traditional or | ||
// finance). So, lookup the respective locale's numberingSystem and return it. | ||
return cldr.main([ "numbers/otherNumberingSystems", nu ]); | ||
} | ||
// Unicode locale extension `u-nu` is set with an explicit numberingSystem. Return it. | ||
return nu; | ||
} | ||
// Return the default numberingSystem. | ||
return cldr.main( "numbers/defaultNumberingSystem" ); | ||
@@ -11,0 +31,0 @@ }; |
define([ | ||
"./numbering-system-digits-map", | ||
"./pattern-properties", | ||
@@ -7,4 +8,4 @@ "./symbol", | ||
"../util/object/flat-extend" | ||
], function( numberPatternProperties, numberSymbol, numberSymbolInvertedMap, numberSymbolName, | ||
objectFlatExtend ) { | ||
], function( numberNumberingSystemDigitsMap, numberPatternProperties, numberSymbol, | ||
numberSymbolInvertedMap, numberSymbolName, objectFlatExtend ) { | ||
@@ -21,3 +22,4 @@ /** | ||
return function( pattern, cldr ) { | ||
var negativePattern, negativeProperties; | ||
var invertedNuDigitsMap, invertedNuDigitsMapSanityCheck, negativePattern, negativeProperties, | ||
nuDigitsMap = numberNumberingSystemDigitsMap( cldr ); | ||
@@ -27,2 +29,16 @@ pattern = pattern.split( ";" ); | ||
negativeProperties = numberPatternProperties( negativePattern ); | ||
if ( nuDigitsMap ) { | ||
invertedNuDigitsMap = nuDigitsMap.split( "" ).reduce(function( object, localizedDigit, i ) { | ||
object[ localizedDigit ] = String( i ); | ||
return object; | ||
}, {} ); | ||
invertedNuDigitsMapSanityCheck = "0123456789".split( "" ).reduce(function( object, digit ) { | ||
object[ digit ] = "invalid"; | ||
return object; | ||
}, {} ); | ||
invertedNuDigitsMap = objectFlatExtend( | ||
invertedNuDigitsMapSanityCheck, | ||
invertedNuDigitsMap | ||
); | ||
} | ||
@@ -37,2 +53,4 @@ // 0: @infinitySymbol [String] Infinity symbol. | ||
// 3: @negativeSuffix [String] Negative suffix with percent or per mille stripped out. | ||
// 4: @invertedNuDigitsMap [Object] Inverted digits map if numbering system is different than | ||
// `latn` augmented with sanity check (similar to invertedSymbolMap). | ||
return [ | ||
@@ -42,3 +60,4 @@ numberSymbol( "infinity", cldr ), | ||
negativeProperties[ 0 ], | ||
negativeProperties[ 10 ].replace( "%", "" ).replace( "\u2030", "" ) | ||
negativeProperties[ 10 ].replace( "%", "" ).replace( "\u2030", "" ), | ||
invertedNuDigitsMap | ||
]; | ||
@@ -45,0 +64,0 @@ }; |
@@ -18,4 +18,4 @@ define([ | ||
return function( value, properties ) { | ||
var aux, infinitySymbol, invertedSymbolMap, localizedSymbolsRe, negativePrefix, negativeSuffix, | ||
number, prefix, suffix; | ||
var aux, infinitySymbol, invertedNuDigitsMap, invertedSymbolMap, localizedDigitRe, | ||
localizedSymbolsRe, negativePrefix, negativeSuffix, number, prefix, suffix; | ||
@@ -26,2 +26,3 @@ infinitySymbol = properties[ 0 ]; | ||
negativeSuffix = properties[ 3 ]; | ||
invertedNuDigitsMap = properties[ 4 ]; | ||
@@ -38,2 +39,3 @@ // Infinite number. | ||
// TODO: Create it during setup, i.e., make it a property. | ||
localizedSymbolsRe = new RegExp( | ||
@@ -51,2 +53,17 @@ Object.keys( invertedSymbolMap ).map(function( localizedSymbol ) { | ||
// Reverse localized numbering system. | ||
if ( invertedNuDigitsMap ) { | ||
// TODO: Create it during setup, i.e., make it a property. | ||
localizedDigitRe = new RegExp( | ||
Object.keys( invertedNuDigitsMap ).map(function( localizedDigit ) { | ||
return regexpEscape( localizedDigit ); | ||
}).join( "|" ), | ||
"g" | ||
); | ||
value = value.replace( localizedDigitRe, function( localizedDigit ) { | ||
return invertedNuDigitsMap[ localizedDigit ]; | ||
}); | ||
} | ||
// Is it a valid number? | ||
@@ -53,0 +70,0 @@ value = value.match( numberNumberRe ); |
define([ | ||
"cldr", | ||
"make-plural", | ||
"./core", | ||
"./common/validate", | ||
"./common/validate/cldr", | ||
"./common/validate/default-locale", | ||
"./common/validate/parameter-key-presence", | ||
"./common/validate/parameter-presence", | ||
"./common/validate/parameter-type", | ||
"./common/validate/parameter-type/number", | ||
"./common/validate/parameter-type/plain-object", | ||
"./plural/form", | ||
"./common/format-message" | ||
], function( Globalize, validate, validateCldr, validateDefaultLocale, validateParameterKeyPresence, | ||
validateParameterPresence, validateParameterType, validateParameterTypeNumber, | ||
validateParameterTypePlainObject, pluralForm, formatMessage ) { | ||
"cldr/supplemental" | ||
], function( Cldr, MakePlural, Globalize, validateCldr, validateDefaultLocale, | ||
validateParameterPresence, validateParameterType, validateParameterTypeNumber ) { | ||
/** | ||
* .formatPlural( value, data, formatValue ) | ||
* .plural( value ) | ||
* | ||
* @value [Number] | ||
* | ||
* @messageData [JSON] eg. { one: "{0} second", other: "{0} seconds" } | ||
* | ||
* @formatValue [String|Number] It defaults to `value`. It's used to replace the | ||
* {0} variable of plural messages. | ||
* | ||
* Return the appropriate message based on value's plural group: zero | one | | ||
* two | few | many | other. | ||
* Return the corresponding form (zero | one | two | few | many | other) of a | ||
* value given locale. | ||
*/ | ||
Globalize.formatPlural = | ||
Globalize.prototype.formatPlural = function( value, messageData, formatValue ) { | ||
var form; | ||
// Note: validateParameterTypeNumber( value, "value" ) is deferred to this.plural(). | ||
Globalize.plural = | ||
Globalize.prototype.plural = function( value ) { | ||
validateParameterPresence( value, "value" ); | ||
validateParameterPresence( messageData, "messageData" ); | ||
validateParameterTypePlainObject( messageData, "messageData" ); | ||
validateParameterType( | ||
formatValue, | ||
"formatValue", | ||
formatValue === undefined || typeof formatValue === "string" || | ||
typeof formatValue === "number", | ||
"String or Number" | ||
); | ||
form = this.plural( value ); | ||
// formatValue defaults to value, but it accepts anything including empty strings. | ||
formatValue = formatValue === undefined ? value : formatValue; | ||
validateParameterKeyPresence( messageData, "messageData", form ); | ||
return formatMessage( messageData[ form ], [ formatValue ] ); | ||
validateParameterTypeNumber( value, "value" ); | ||
return this.pluralGenerator()( value ); | ||
}; | ||
/** | ||
* .plural( value ) | ||
* .pluralGenerator() | ||
* | ||
* Return a plural function (of the form below). | ||
* | ||
* fn( value ) | ||
* | ||
* @value [Number] | ||
* | ||
* Return the corresponding form (zero | one | two | few | many | other) of a | ||
* value given locale. | ||
* Return the corresponding form (zero | one | two | few | many | other) of a value given the | ||
* default/instance locale. | ||
*/ | ||
Globalize.plural = | ||
Globalize.prototype.plural = function( value ) { | ||
var cldr, form; | ||
Globalize.pluralGenerator = | ||
Globalize.prototype.pluralGenerator = function() { | ||
var cldr, plural; | ||
validateParameterPresence( value, "value" ); | ||
validateParameterTypeNumber( value, "value" ); | ||
cldr = this.cldr; | ||
@@ -77,10 +50,18 @@ | ||
cldr.on( "get", validateCldr ); | ||
form = pluralForm( value, cldr ); | ||
cldr.supplemental( "plurals-type-cardinal/{language}" ); | ||
cldr.off( "get", validateCldr ); | ||
validate( "E_INVALID_CLDR", "{description}", typeof form === "string", { | ||
description: "Missing rules to deduce plural form of `" + value + "`" | ||
}); | ||
// Set CLDR data | ||
MakePlural.rules = { | ||
cardinal: cldr.supplemental( "plurals-type-cardinal" ) | ||
}; | ||
return form; | ||
plural = MakePlural( cldr.attributes.language, { "no_tests": true } ); | ||
return function( value ) { | ||
validateParameterPresence( value, "value" ); | ||
validateParameterTypeNumber( value, "value" ); | ||
return plural( value ); | ||
}; | ||
}; | ||
@@ -87,0 +68,0 @@ |
@@ -33,3 +33,2 @@ require.config({ | ||
// plural | ||
"./functional/plural/format-plural", | ||
"./functional/plural/plural" | ||
@@ -36,0 +35,0 @@ |
@@ -74,3 +74,3 @@ define([ | ||
assert.equal( Globalize( "pt" ).formatDate( date, { skeleton: "Ehms" } ), "qua, 5:35:07 PM" ); | ||
assert.equal( Globalize( "pt" ).formatDate( date, { skeleton: "GyMMMEd" } ), "qua, 15 'de' set 'de' 2010 d.C." ); | ||
assert.equal( Globalize( "pt" ).formatDate( date, { skeleton: "GyMMMEd" } ), "qua, 15 de set de 2010 d.C." ); | ||
}); | ||
@@ -77,0 +77,0 @@ |
@@ -6,6 +6,9 @@ define([ | ||
"json!cldr-data/main/es/numbers.json", | ||
"json!cldr-data/main/zh/numbers.json", | ||
"json!cldr-data/supplemental/likelySubtags.json", | ||
"json!cldr-data/supplemental/numberingSystems.json", | ||
"../../util", | ||
"globalize/number" | ||
], function( Globalize, arNumbers, enNumbers, esNumbers, likelySubtags, util ) { | ||
], function( Globalize, arNumbers, enNumbers, esNumbers, zhNumbers, likelySubtags, numberingSystems, | ||
util ) { | ||
@@ -18,3 +21,5 @@ var pi = 3.14159265359; | ||
enNumbers, | ||
esNumbers | ||
esNumbers, | ||
zhNumbers, | ||
numberingSystems | ||
); | ||
@@ -60,3 +65,4 @@ } | ||
assert.equal( Globalize( "es" ).formatNumber( pi ), "3,142" ); | ||
assert.equal( Globalize( "ar" ).formatNumber( pi ), "3٫142" ); | ||
assert.equal( Globalize( "ar" ).formatNumber( pi ), "٣٫١٤٢" ); | ||
assert.equal( Globalize( "zh-u-nu-native" ).formatNumber( pi ), "三.一四二" ); | ||
assert.equal( Globalize.formatNumber( 99999999.99 ), "99,999,999.99" ); | ||
@@ -105,5 +111,5 @@ | ||
assert.equal( Globalize.formatNumber( pi, { style: "percent" } ), "314%" ); | ||
assert.equal( Globalize( "ar" ).formatNumber( pi, { style: "percent" } ), "314٪" ); | ||
assert.equal( Globalize( "ar" ).formatNumber( pi, { style: "percent" } ), "٣١٤٪" ); | ||
}); | ||
}); |
@@ -7,8 +7,11 @@ define([ | ||
"json!cldr-data/main/sv/numbers.json", | ||
"json!cldr-data/main/zh/numbers.json", | ||
"json!cldr-data/supplemental/likelySubtags.json", | ||
"json!cldr-data/supplemental/numberingSystems.json", | ||
"../../util", | ||
"globalize/number" | ||
], function( Globalize, arNumbers, enNumbers, esNumbers, svNumbers, likelySubtags, util ) { | ||
], function( Globalize, arNumbers, enNumbers, esNumbers, svNumbers, zhNumbers, likelySubtags, | ||
numberingSystems, util ) { | ||
var ar, es, sv; | ||
var ar, es, sv, zh; | ||
@@ -20,3 +23,5 @@ function extraSetup() { | ||
esNumbers, | ||
svNumbers | ||
svNumbers, | ||
zhNumbers, | ||
numberingSystems | ||
); | ||
@@ -31,2 +36,3 @@ } | ||
sv = new Globalize( "sv" ); | ||
zh = new Globalize( "zh-u-nu-native" ); | ||
Globalize.locale( "en" ); | ||
@@ -90,3 +96,4 @@ }, | ||
assert.equal( es.parseNumber( "3,14" ), 3.14 ); | ||
assert.equal( ar.parseNumber( "3٫14" ), 3.14 ); | ||
assert.equal( ar.parseNumber( "٣٫١٤" ), 3.14 ); | ||
assert.equal( zh.parseNumber( "三.一四" ), 3.14 ); | ||
assert.equal( Globalize.parseNumber( "3.00" ), 3 ); | ||
@@ -117,3 +124,3 @@ assert.equal( Globalize.parseNumber( "12735.0" ), 12735 ); | ||
assert.equal( Globalize.parseNumber( "0.5%" ), 0.005 ); | ||
assert.equal( ar.parseNumber( "50٪" ), 0.5 ); | ||
assert.equal( ar.parseNumber( "٥٠٪" ), 0.5 ); | ||
assert.equal( Globalize.parseNumber( "-10%" ), -0.1 ); | ||
@@ -120,0 +127,0 @@ }); |
@@ -11,2 +11,16 @@ define([ | ||
Globalize.load( plurals ); | ||
// Temporary fix due to CLDR v26 regression about pt_BR plural | ||
// http://unicode.org/cldr/trac/ticket/7178 | ||
Globalize.load({ | ||
"supplemental": { | ||
"plurals-type-cardinal": { | ||
pt: { | ||
"pluralRule-count-one": "i = 0,1", | ||
"pluralRule-count-other": "" | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
@@ -38,17 +52,2 @@ | ||
}); | ||
// Assert E_INVALID_CLDR "Missing rules to deduce plural form of `1`". | ||
Globalize.load({ | ||
supplemental: { | ||
"plurals-type-cardinal": { en: {} } | ||
} | ||
}); | ||
assert.throws(function() { | ||
Globalize.plural( 1 ); | ||
}, function E_INVALID_CLDR( error ) { | ||
return error.code === "E_INVALID_CLDR" && | ||
"description" in error && | ||
error.description === "Missing rules to deduce plural form of `1`"; | ||
}, "Expected \"E_MISSING_CLDR\" to be thrown" ); | ||
}); | ||
@@ -59,6 +58,64 @@ | ||
assert.equal( Globalize.plural( 0 ), "other" ); | ||
assert.equal( Globalize.plural( 0.14 ), "other" ); | ||
assert.equal( Globalize( "en" ).plural( 0 ), "other" ); | ||
assert.equal( Globalize( "en" ).plural( 1 ), "one" ); | ||
assert.equal( Globalize( "en" ).plural( 2 ), "other" ); | ||
assert.equal( Globalize( "en" ).plural( 1412 ), "other" ); | ||
assert.equal( Globalize( "en" ).plural( 0.14 ), "other" ); | ||
assert.equal( Globalize( "en" ).plural( 3.14 ), "other" ); | ||
assert.equal( Globalize( "ar" ).plural( 0 ), "zero" ); | ||
}); | ||
assert.equal( Globalize( "ar" ).plural( 1 ), "one" ); | ||
assert.equal( Globalize( "ar" ).plural( 2 ), "two" ); | ||
assert.equal( Globalize( "ar" ).plural( 3 ), "few" ); | ||
assert.equal( Globalize( "ar" ).plural( 6 ), "few" ); | ||
assert.equal( Globalize( "ar" ).plural( 9 ), "few" ); | ||
assert.equal( Globalize( "ar" ).plural( 10 ), "few" ); | ||
assert.equal( Globalize( "ar" ).plural( 11 ), "many" ); | ||
assert.equal( Globalize( "ar" ).plural( 15 ), "many" ); | ||
assert.equal( Globalize( "ar" ).plural( 21 ), "many" ); | ||
assert.equal( Globalize( "ar" ).plural( 70 ), "many" ); | ||
assert.equal( Globalize( "ar" ).plural( 99 ), "many" ); | ||
assert.equal( Globalize( "ar" ).plural( 100 ), "other" ); | ||
assert.equal( Globalize( "ar" ).plural( 101 ), "other" ); | ||
assert.equal( Globalize( "ar" ).plural( 102 ), "other" ); | ||
assert.equal( Globalize( "ar" ).plural( 103 ), "few" ); | ||
assert.equal( Globalize( "ar" ).plural( 111 ), "many" ); | ||
assert.equal( Globalize( "ar" ).plural( 199 ), "many" ); | ||
assert.equal( Globalize( "ar" ).plural( 3.14 ), "other" ); | ||
assert.equal( Globalize( "ja" ).plural( 0 ), "other" ); | ||
assert.equal( Globalize( "ja" ).plural( 1 ), "other" ); | ||
assert.equal( Globalize( "ja" ).plural( 2 ), "other" ); | ||
assert.equal( Globalize( "ja" ).plural( 3.14 ), "other" ); | ||
assert.equal( Globalize( "pt" ).plural( 0 ), "one" ); | ||
assert.equal( Globalize( "pt" ).plural( 1 ), "one" ); | ||
assert.equal( Globalize( "pt" ).plural( 2 ), "other" ); | ||
assert.equal( Globalize( "pt" ).plural( 0.1 ), "one" ); | ||
assert.equal( Globalize( "pt" ).plural( 3.14 ), "other" ); | ||
assert.equal( Globalize( "ru" ).plural( 0 ), "many" ); | ||
assert.equal( Globalize( "ru" ).plural( 1 ), "one" ); | ||
assert.equal( Globalize( "ru" ).plural( 2 ), "few" ); | ||
assert.equal( Globalize( "ru" ).plural( 3 ), "few" ); | ||
assert.equal( Globalize( "ru" ).plural( 4 ), "few" ); | ||
assert.equal( Globalize( "ru" ).plural( 5 ), "many" ); | ||
assert.equal( Globalize( "ru" ).plural( 6 ), "many" ); | ||
assert.equal( Globalize( "ru" ).plural( 9 ), "many" ); | ||
assert.equal( Globalize( "ru" ).plural( 11 ), "many" ); | ||
assert.equal( Globalize( "ru" ).plural( 12 ), "many" ); | ||
assert.equal( Globalize( "ru" ).plural( 19 ), "many" ); | ||
assert.equal( Globalize( "ru" ).plural( 21 ), "one" ); | ||
assert.equal( Globalize( "ru" ).plural( 22 ), "few" ); | ||
assert.equal( Globalize( "ru" ).plural( 29 ), "many" ); | ||
assert.equal( Globalize( "ru" ).plural( 3.14 ), "other" ); | ||
assert.equal( Globalize( "zh" ).plural( 0 ), "other" ); | ||
assert.equal( Globalize( "zh" ).plural( 1 ), "other" ); | ||
assert.equal( Globalize( "zh" ).plural( 2 ), "other" ); | ||
assert.equal( Globalize( "zh" ).plural( 3.14 ), "other" ); | ||
}); | ||
}); |
@@ -5,3 +5,2 @@ require.config({ | ||
"cldr-data": "../external/cldr-data", | ||
CLDRPluralRuleParser: "../external/CLDRPluralRuleParser/src/CLDRPluralRuleParser", | ||
json: "../external/requirejs-plugins/src/json", | ||
@@ -42,9 +41,6 @@ src: "../src", | ||
"./unit/number/parse-properties", | ||
"./unit/number/parse", | ||
"./unit/number/parse" | ||
/* plural */ | ||
"./unit/plural/form" | ||
], function() { | ||
QUnit.start(); | ||
}); |
@@ -551,2 +551,12 @@ define([ | ||
/** | ||
* Literal | ||
*/ | ||
QUnit.test( "should format literal (')", function( assert ) { | ||
assert.equal( format( date1, properties( "yyyy.MM.dd G 'at' HH:mm:ss", cldr ) ), | ||
"1982.01.02 AD at 09:05:59" ); | ||
assert.equal( format( date1, properties( "hh 'o''clock' a", cldr ) ), "09 o'clock AM" ); | ||
}); | ||
}); |
@@ -394,3 +394,3 @@ define([ | ||
QUnit.test( "should format timezone (z)", function( assert ) { | ||
QUnit.test( "should parse timezone (z)", function( assert ) { | ||
[ "z", "zz", "zzz", "zzzz" ].forEach(function( z ) { | ||
@@ -411,3 +411,3 @@ assertParseTimezone( assert, "GMT", z, cldr, 0 ); | ||
QUnit.test( "should format timezone (Z)", function( assert ) { | ||
QUnit.test( "should parse timezone (Z)", function( assert ) { | ||
assertParseTimezone( assert, "+0000", "Z", cldr, 0 ); | ||
@@ -432,3 +432,3 @@ assertParseTimezone( assert, "+0000", "ZZ", cldr, 0 ); | ||
QUnit.test( "should format timezone (O)", function( assert ) { | ||
QUnit.test( "should parse timezone (O)", function( assert ) { | ||
assertParseTimezone( assert, "GMT", "O", cldr, 0 ); | ||
@@ -444,3 +444,3 @@ assertParseTimezone( assert, "GMT", "OOOO", cldr, 0 ); | ||
QUnit.test( "should format timezone (X)", function( assert ) { | ||
QUnit.test( "should parse timezone (X)", function( assert ) { | ||
assertParseTimezone( assert, "Z", "X", cldr, 0 ); | ||
@@ -470,3 +470,3 @@ assertParseTimezone( assert, "Z", "XX", cldr, 0 ); | ||
QUnit.test( "should format timezone (x)", function( assert ) { | ||
QUnit.test( "should parse timezone (x)", function( assert ) { | ||
assertParseTimezone( assert, "+00", "x", cldr, 0 ); | ||
@@ -496,2 +496,9 @@ assertParseTimezone( assert, "+0000", "xx", cldr, 0 ); | ||
QUnit.test( "should parse literal (')", function( assert ) { | ||
var date = new Date(); | ||
date.setHours( 9 ); | ||
date = startOf( date, "hour" ); | ||
assertParse( assert, "09 o'clock AM", "hh 'o''clock' a", cldr, date ); | ||
}); | ||
}); |
@@ -8,9 +8,11 @@ define([ | ||
"json!cldr-data/main/es/numbers.json", | ||
"json!cldr-data/supplemental/likelySubtags.json" | ||
], function( Cldr, format, properties, arNumbers, enNumbers, esNumbers, | ||
likelySubtags ) { | ||
"json!cldr-data/main/zh/numbers.json", | ||
"json!cldr-data/supplemental/likelySubtags.json", | ||
"json!cldr-data/supplemental/numberingSystems.json" | ||
], function( Cldr, format, properties, arNumbers, enNumbers, esNumbers, zhNumbers, likelySubtags, | ||
numberingSystems ) { | ||
// 1: Earth average diameter according to: | ||
// http://www.wolframalpha.com/input/?i=earth+diameter | ||
var ar, en, es, | ||
var ar, en, es, zh, | ||
deci = 0.1, | ||
@@ -24,3 +26,5 @@ earthDiameter = 12735, /* 1 */ | ||
esNumbers, | ||
likelySubtags | ||
zhNumbers, | ||
likelySubtags, | ||
numberingSystems | ||
); | ||
@@ -31,2 +35,3 @@ | ||
es = new Cldr( "es" ); | ||
zh = new Cldr( "zh-u-nu-native" ); | ||
@@ -86,3 +91,4 @@ QUnit.module( "Number Format" ); | ||
assert.equal( format( pi, properties( "0.##", es ) ), "3,14" ); | ||
assert.equal( format( pi, properties( "0.##", ar ) ), "3٫14" ); | ||
assert.equal( format( pi, properties( "0.##", ar ) ), "٣٫١٤" ); | ||
assert.equal( format( pi, properties( "0.##", zh ) ), "三.一四" ); | ||
}); | ||
@@ -223,3 +229,3 @@ | ||
QUnit.test( "should localize percent symbol (%)", function( assert ) { | ||
assert.equal( format( 0.5, properties( "#0%", ar ) ), "50٪" ); | ||
assert.equal( format( 0.5, properties( "#0%", ar ) ), "٥٠٪" ); | ||
}); | ||
@@ -251,3 +257,3 @@ | ||
QUnit.test( "should localize per mille symbol (\u2030)", function( assert ) { | ||
assert.equal( format( 0.5, properties( "#0\u2030", ar ) ), "500؉" ); | ||
assert.equal( format( 0.5, properties( "#0\u2030", ar ) ), "٥٠٠؉" ); | ||
}); | ||
@@ -278,2 +284,10 @@ | ||
/** | ||
* Literal | ||
*/ | ||
QUnit.test( "should format literal (')", function( assert ) { | ||
assert.equal( format( 69900, properties( "'$'#,##0", en ) ), "$69,900" ); | ||
}); | ||
}); |
@@ -10,7 +10,9 @@ define([ | ||
"json!cldr-data/main/sv/numbers.json", | ||
"json!cldr-data/supplemental/likelySubtags.json" | ||
], function( Cldr, parse, properties, arNumbers, enNumbers, esNumbers, ruNumbers, | ||
svNumbers, likelySubtags ) { | ||
"json!cldr-data/main/zh/numbers.json", | ||
"json!cldr-data/supplemental/likelySubtags.json", | ||
"json!cldr-data/supplemental/numberingSystems.json" | ||
], function( Cldr, parse, properties, arNumbers, enNumbers, esNumbers, ruNumbers, svNumbers, | ||
zhNumbers, likelySubtags, numberingSystems ) { | ||
var ar, en, es, ru, sv; | ||
var ar, en, es, ru, sv, zh; | ||
@@ -23,3 +25,5 @@ Cldr.load( | ||
svNumbers, | ||
likelySubtags | ||
zhNumbers, | ||
likelySubtags, | ||
numberingSystems | ||
); | ||
@@ -32,2 +36,3 @@ | ||
sv = new Cldr( "sv" ); | ||
zh = new Cldr( "zh-u-nu-native" ); | ||
@@ -66,3 +71,4 @@ QUnit.module( "Number Parse" ); | ||
assert.equal( parse( "3,14", properties( "0.##", es ) ), 3.14 ); | ||
assert.equal( parse( "3٫14", properties( "0.##", ar ) ), 3.14 ); | ||
assert.equal( parse( "٣٫١٤", properties( "0.##", ar ) ), 3.14 ); | ||
assert.equal( parse( "三.一四", properties( "0.##", zh ) ), 3.14 ); | ||
assert.equal( parse( "3.00", properties( "0.##", en ) ), 3 ); | ||
@@ -100,3 +106,3 @@ }); | ||
QUnit.test( "should localize percent symbol (%)", function( assert ) { | ||
assert.equal( parse( "50٪", properties( "#0%", ar ) ), 0.5 ); | ||
assert.equal( parse( "٥٠٪", properties( "#0%", ar ) ), 0.5 ); | ||
}); | ||
@@ -125,3 +131,3 @@ | ||
assert.equal( parse( "500‰", properties( "#0‰", en ) ), 0.5 ); | ||
assert.equal( parse( "500؉", properties( "#0\u2030", ar ) ), 0.5 ); | ||
assert.equal( parse( "٥٠٠؉", properties( "#0\u2030", ar ) ), 0.5 ); | ||
}); | ||
@@ -161,3 +167,2 @@ | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 2 instances in 1 package
1
389028
171
10166
483
2
+ Addedcldrjs@0.3.10(transitive)
- Removedcldrjs@0.3.9(transitive)
Updatedcldrjs@0.3.10