zpt
Version:
Zenon Page Templates - JS (ZPT-JS)
1,478 lines (1,333 loc) • 136 kB
JavaScript
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.MessageFormat = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var reserved = require('reserved-words');
var parse = require('messageformat-parser').parse;
/** Creates a new message compiler. Called internally from {@link MessageFormat#compile}.
*
* @class
* @param {MessageFormat} mf - A MessageFormat instance
* @property {object} locales - The locale identifiers that are used by the compiled functions
* @property {object} runtime - Names of the core runtime functions that are used by the compiled functions
* @property {object} formatters - The formatter functions that are used by the compiled functions
*/
function Compiler(mf) {
this.mf = mf;
this.lc = null;
this.locales = {};
this.runtime = {};
this.formatters = {};
}
module.exports = Compiler;
/** Utility function for quoting an Object's key value iff required
*
* Quotes the key if it contains invalid characters or is an
* ECMAScript 3rd Edition reserved word (for IE8).
*/
Compiler.propname = function(key, obj) {
if (/^[A-Z_$][0-9A-Z_$]*$/i.test(key) &&
['break', 'continue', 'delete', 'else', 'for', 'function', 'if', 'in', 'new',
'return', 'this', 'typeof', 'var', 'void', 'while', 'with', 'case', 'catch',
'default', 'do', 'finally', 'instanceof', 'switch', 'throw', 'try'].indexOf(key) < 0) {
return obj ? obj + '.' + key : key;
} else {
var jkey = JSON.stringify(key);
return obj ? obj + '[' + jkey + ']' : jkey;
}
}
/** Utility function for escaping a function name iff required
*/
Compiler.funcname = function(key) {
var fn = key.trim().replace(/\W+/g, '_');
return reserved.check(fn, 'es2015', true) || /^\d/.test(fn) ? '_' + fn : fn;
}
/** Utility formatter function for enforcing Bidi Structured Text by using UCC
*
* List inlined from data extracted from CLDR v27 & v28
* To verify/recreate, use the following:
*
* git clone https://github.com/unicode-cldr/cldr-misc-full.git
* cd cldr-misc-full/main/
* grep characterOrder -r . | tr '"/' '\t' | cut -f2,6 | grep -C4 right-to-left
*/
Compiler.bidiMarkText = function(text, locale) {
function isLocaleRTL(locale) {
var rtlLanguages = ['ar', 'ckb', 'fa', 'he', 'ks($|[^bfh])', 'lrc', 'mzn',
'pa-Arab', 'ps', 'ug', 'ur', 'uz-Arab', 'yi'];
return new RegExp('^' + rtlLanguages.join('|^')).test(locale);
}
var mark = JSON.stringify(isLocaleRTL(locale) ? '\u200F' : '\u200E');
return mark + ' + ' + text + ' + ' + mark;
}
/** @private */
Compiler.prototype.cases = function(token, plural) {
var needOther = true;
var r = token.cases.map(function(c) {
if (c.key === 'other') needOther = false;
var s = c.tokens.map(function(tok) { return this.token(tok, plural); }, this);
return Compiler.propname(c.key) + ': ' + (s.join(' + ') || '""');
}, this);
if (needOther) throw new Error("No 'other' form found in " + JSON.stringify(token));
return '{ ' + r.join(', ') + ' }';
}
/** @private */
Compiler.prototype.token = function(token, plural) {
if (typeof token == 'string') return JSON.stringify(token);
var fn, args = [ Compiler.propname(token.arg, 'd') ];
switch (token.type) {
case 'argument':
return this.mf.bidiSupport ? Compiler.bidiMarkText(args[0], this.lc) : args[0];
case 'select':
fn = 'select';
args.push(this.cases(token, this.mf.strictNumberSign ? null : plural));
this.runtime.select = true;
break;
case 'selectordinal':
fn = 'plural';
args.push(0, Compiler.funcname(this.lc), this.cases(token, token), 1);
this.locales[this.lc] = true;
this.runtime.plural = true;
break;
case 'plural':
fn = 'plural';
args.push(token.offset || 0, Compiler.funcname(this.lc), this.cases(token, token));
this.locales[this.lc] = true;
this.runtime.plural = true;
break;
case 'function':
if (this.mf.intlSupport && !(token.key in this.mf.fmt) && (token.key in this.mf.constructor.formatters)) {
var fmt = this.mf.constructor.formatters[token.key];
this.mf.fmt[token.key] = (typeof fmt(this.mf) == 'function') ? fmt(this.mf) : fmt;
}
if (!this.mf.fmt[token.key]) throw new Error('Formatting function ' + JSON.stringify(token.key) + ' not found!');
args.push(JSON.stringify(this.lc));
if (token.params) switch (token.params.length) {
case 0: break;
case 1: args.push(JSON.stringify(token.params[0])); break;
default: args.push(JSON.stringify(token.params)); break;
}
fn = Compiler.propname(token.key, 'fmt');
this.formatters[token.key] = true;
break;
case 'octothorpe':
if (!plural) return '"#"';
fn = 'number';
args = [ Compiler.propname(plural.arg, 'd'), JSON.stringify(plural.arg) ];
if (plural.offset) args.push(plural.offset);
this.runtime.number = true;
break;
}
if (!fn) throw new Error('Parser error for token ' + JSON.stringify(token));
return fn + '(' + args.join(', ') + ')';
};
/** Recursively compile a string or a tree of strings to JavaScript function sources
*
* If `src` is an object with a key that is also present in `plurals`, the key
* in question will be used as the locale identifier for its value. To disable
* the compile-time checks for plural & selectordinal keys while maintaining
* multi-locale support, use falsy values in `plurals`.
*
* @param {string|object} src - the source for which the JS code should be generated
* @param {string} lc - the default locale
* @param {object} plurals - a map of pluralization keys for all available locales
*/
Compiler.prototype.compile = function(src, lc, plurals) {
if (typeof src != 'object') {
this.lc = lc;
var pc = plurals[lc] || { cardinal: [], ordinal: [] };
var r = parse(src, pc).map(function(token) { return this.token(token); }, this);
return 'function(d) { return ' + (r.join(' + ') || '""') + '; }';
} else {
var result = {};
for (var key in src) {
var lcKey = plurals.hasOwnProperty(key) ? key : lc;
result[key] = this.compile(src[key], lcKey, plurals);
}
return result;
}
}
},{"messageformat-parser":8,"reserved-words":10}],2:[function(require,module,exports){
/** @file messageformat.js - ICU PluralFormat + SelectFormat for JavaScript
*
* @author Alex Sexton - @SlexAxton, Eemeli Aro
* @version 1.0.2
* @copyright 2012-2016 Alex Sexton, Eemeli Aro, and Contributors
* @license To use or fork, MIT. To contribute back, Dojo CLA
*/
var Compiler = require('./compiler');
var Runtime = require('./runtime');
/** Utility getter/wrapper for pluralization functions from
* {@link http://github.com/eemeli/make-plural.js make-plural}
*
* @private
*/
function getPluralFunc(locale, noPluralKeyChecks) {
var plurals = require('make-plural/plurals');
var pluralCategories = require('make-plural/pluralCategories');
for (var l = locale; l; l = l.replace(/[-_]?[^-_]*$/, '')) {
var pf = plurals[l];
if (pf) {
var pc = noPluralKeyChecks ? { cardinal: [], ordinal: [] } : (pluralCategories[l] || {});
var fn = function() { return pf.apply(this, arguments); };
fn.toString = function() { return pf.toString(); };
fn.cardinal = pc.cardinal;
fn.ordinal = pc.ordinal;
return fn;
}
}
throw new Error('Localisation function not found for locale ' + JSON.stringify(locale));
}
/** Create a new message formatter
*
* If `locale` is not set, calls to `compile()` will fetch the default locale
* each time. A string `locale` will create a single-locale MessageFormat
* instance, with pluralisation rules fetched from the Unicode CLDR using
* {@link http://github.com/eemeli/make-plural.js make-plural}.
*
* Using an array of strings as `locale` will create a MessageFormat object
* with multi-language support, with pluralisation rules fetched as above. To
* select which to use, use the second parameter of `compile()`, or use message
* keys corresponding to your locales.
*
* Using an object `locale` with all properties of type `function` allows for
* the use of custom/externally defined pluralisation rules.
*
* @class
* @param {string|string[]|Object.<string,function>} [locale] - The locale(s) to use
*/
function MessageFormat(locale) {
this.pluralFuncs = {};
if (locale) {
if (typeof locale == 'string') {
this.pluralFuncs[locale] = getPluralFunc(locale);
} else if (Array.isArray(locale)) {
locale.forEach(function(lc) { this.pluralFuncs[lc] = getPluralFunc(lc); }, this);
} else if (typeof locale == 'object') {
for (var lc in locale) if (locale.hasOwnProperty(lc)) {
if (typeof locale[lc] != 'function') throw new Error('Expected function value for locale ' + JSON.stringify(lc));
this.pluralFuncs[lc] = locale[lc];
}
}
}
this.fmt = {};
this.runtime = new Runtime(this);
}
/** The default locale
*
* Read by `compile()` when no locale has been previously set
*
* @memberof MessageFormat
* @default 'en'
*/
MessageFormat.defaultLocale = 'en';
/** Escape special characaters
*
* Prefix the characters `#`, `{`, `}` and `\` in the input string with a `\`.
* This will allow those characters to not be considered as MessageFormat
* control characters.
*
* @param {string} str - The input string
* @returns {string} The escaped string
*/
MessageFormat.escape = function(str) {
return str.replace(/[#{}\\]/g, '\\$&');
}
/** Default number formatting functions in the style of ICU's
* {@link http://icu-project.org/apiref/icu4j/com/ibm/icu/text/MessageFormat.html simpleArg syntax}
* implemented using the
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl Intl}
* object defined by ECMA-402.
*
* **Note**: Intl is not defined in default Node until 0.11.15 / 0.12.0, so
* earlier versions require a {@link https://www.npmjs.com/package/intl polyfill}.
* Therefore {@link MessageFormat.intlSupport} needs to be true for these default
* functions to be available for inclusion in the output.
*
* @see MessageFormat#setIntlSupport
*
* @namespace
*/
MessageFormat.formatters = {
/** Represent a number as an integer, percent or currency value
*
* Available in MessageFormat strings as `{VAR, number, integer|percent|currency}`.
* Internally, calls Intl.NumberFormat with appropriate parameters. `currency` will
* default to USD; to change, set `MessageFormat#currency` to the appropriate
* three-letter currency code.
*
* @param {number} value - The value to operate on
* @param {string} type - One of `'integer'`, `'percent'` , or `currency`
*
* @example
* var mf = new MessageFormat('en').setIntlSupport(true);
* mf.currency = 'EUR'; // needs to be set before first compile() call
*
* mf.compile('{N} is almost {N, number, integer}')({ N: 3.14 })
* // '3.14 is almost 3'
*
* mf.compile('{P, number, percent} complete')({ P: 0.99 })
* // '99% complete'
*
* mf.compile('The total is {V, number, currency}.')({ V: 5.5 })
* // 'The total is €5.50.'
*/
number: function(self) {
return new Function("v,lc,p",
"return new Intl.NumberFormat(lc,\n" +
" p=='integer' ? {maximumFractionDigits:0}\n" +
" : p=='percent' ? {style:'percent'}\n" +
" : p=='currency' ? {style:'currency', currency:'" + (self.currency || 'USD') + "', minimumFractionDigits:2, maximumFractionDigits:2}\n" +
" : {}).format(v)"
);
},
/** Represent a date as a short/default/long/full string
*
* The input value needs to be in a form that the
* {@link https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date Date object}
* can process using its single-argument form, `new Date(value)`.
*
* @param {number|string} value - Either a Unix epoch time in milliseconds, or a string value representing a date
* @param {string} [type='default'] - One of `'short'`, `'default'`, `'long'` , or `full`
*
* @example
* var mf = new MessageFormat(['en', 'fi']).setIntlSupport(true);
*
* mf.compile('Today is {T, date}')({ T: Date.now() })
* // 'Today is Feb 21, 2016'
*
* mf.compile('Tänään on {T, date}', 'fi')({ T: Date.now() })
* // 'Tänään on 21. helmikuuta 2016'
*
* mf.compile('Unix time started on {T, date, full}')({ T: 0 })
* // 'Unix time started on Thursday, January 1, 1970'
*
* var cf = mf.compile('{sys} became operational on {d0, date, short}');
* cf({ sys: 'HAL 9000', d0: '12 January 1999' })
* // 'HAL 9000 became operational on 1/12/1999'
*/
date: function(v,lc,p) {
var o = {day:'numeric', month:'short', year:'numeric'};
switch (p) {
case 'full': o.weekday = 'long';
case 'long': o.month = 'long'; break;
case 'short': o.month = 'numeric';
}
return (new Date(v)).toLocaleDateString(lc, o)
},
/** Represent a time as a short/default/long string
*
* The input value needs to be in a form that the
* {@link https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date Date object}
* can process using its single-argument form, `new Date(value)`.
*
* @param {number|string} value - Either a Unix epoch time in milliseconds, or a string value representing a date
* @param {string} [type='default'] - One of `'short'`, `'default'`, `'long'` , or `full`
*
* @example
* var mf = new MessageFormat(['en', 'fi']).setIntlSupport(true);
*
* mf.compile('The time is now {T, time}')({ T: Date.now() })
* // 'The time is now 11:26:35 PM'
*
* mf.compile('Kello on nyt {T, time}', 'fi')({ T: Date.now() })
* // 'Kello on nyt 23.26.35'
*
* var cf = mf.compile('The Eagle landed at {T, time, full} on {T, date, full}');
* cf({ T: '1969-07-20 20:17:40 UTC' })
* // 'The Eagle landed at 10:17:40 PM GMT+2 on Sunday, July 20, 1969'
*/
time: function(v,lc,p) {
var o = {second:'numeric', minute:'numeric', hour:'numeric'};
switch (p) {
case 'full': case 'long': o.timeZoneName = 'short'; break;
case 'short': delete o.second;
}
return (new Date(v)).toLocaleTimeString(lc, o)
}
};
/** Add custom formatter functions to this MessageFormat instance
*
* The general syntax for calling a formatting function in MessageFormat is
* `{var, fn[, args]*}`, where `var` is the variable that will be set by the
* user code, `fn` determines the formatting function, and `args` is an
* optional comma-separated list of additional arguments.
*
* In JavaScript, each formatting function is called with three parameters;
* the variable value `v`, the current locale `lc`, and (if set) `args` as a
* single string, or an array of strings. Formatting functions should not have
* side effects.
*
* @see MessageFormat.formatters
*
* @memberof MessageFormat
* @param {Object.<string,function>} fmt - A map of formatting functions
* @returns {MessageFormat} The MessageFormat instance, to allow for chaining
*
* @example
* var mf = new MessageFormat('en-GB');
* mf.addFormatters({
* upcase: function(v) { return v.toUpperCase(); },
* locale: function(v, lc) { return lc; },
* prop: function(v, lc, p) { return v[p] }
* });
*
* mf.compile('This is {VAR, upcase}.')({ VAR: 'big' })
* // 'This is BIG.'
*
* mf.compile('The current locale is {_, locale}.')({ _: '' })
* // 'The current locale is en-GB.'
*
* mf.compile('Answer: {obj, prop, a}')({ obj: {q: 3, a: 42} })
* // 'Answer: 42'
*/
MessageFormat.prototype.addFormatters = function(fmt) {
for (var name in fmt) if (fmt.hasOwnProperty(name)) {
this.fmt[name] = fmt[name];
}
return this;
};
/** Disable the validation of plural & selectordinal keys
*
* Previous versions of messageformat.js allowed the use of plural &
* selectordinal statements with any keys; now we throw an error when a
* statement uses a non-numerical key that will never be matched as a
* pluralization category for the current locale.
*
* Use this method to disable the validation and allow usage as previously.
* To re-enable, you'll need to create a new MessageFormat instance.
*
* @returns {MessageFormat} The MessageFormat instance, to allow for chaining
*
* @example
* var mf = new MessageFormat('en');
* var msg = '{X, plural, zero{no answers} one{an answer} other{# answers}}';
*
* mf.compile(msg);
* // Error: Invalid key `zero` for argument `X`. Valid plural keys for this
* // locale are `one`, `other`, and explicit keys like `=0`.
*
* mf.disablePluralKeyChecks();
* mf.compile(msg)({ X: 0 });
* // '0 answers'
*/
MessageFormat.prototype.disablePluralKeyChecks = function() {
this.noPluralKeyChecks = true;
for (var lc in this.pluralFuncs) if (this.pluralFuncs.hasOwnProperty(lc)) {
this.pluralFuncs[lc].cardinal = [];
this.pluralFuncs[lc].ordinal = [];
}
return this;
};
/** Enable or disable the addition of Unicode control characters to all input
* to preserve the integrity of the output when mixing LTR and RTL text.
*
* @see http://cldr.unicode.org/development/development-process/design-proposals/bidi-handling-of-structured-text
*
* @memberof MessageFormat
* @param {boolean} [enable=true]
* @returns {MessageFormat} The MessageFormat instance, to allow for chaining
*
* @example
* // upper case stands for RTL characters, output is shown as rendered
* var mf = new MessageFormat('en');
*
* mf.compile('{0} >> {1} >> {2}')(['first', 'SECOND', 'THIRD']);
* // 'first >> THIRD << SECOND'
*
* mf.setBiDiSupport(true);
* mf.compile('{0} >> {1} >> {2}')(['first', 'SECOND', 'THIRD']);
* // 'first >> SECOND >> THIRD'
*/
MessageFormat.prototype.setBiDiSupport = function(enable) {
this.bidiSupport = !!enable || (typeof enable == 'undefined');
return this;
};
/** Enable or disable support for the default formatters, which require the
* `Intl` object. Note that this can't be autodetected, as the environment
* in which the formatted text is compiled into Javascript functions is not
* necessarily the same environment in which they will get executed.
*
* @see MessageFormat.formatters
*
* @memberof MessageFormat
* @param {boolean} [enable=true]
* @returns {MessageFormat} The MessageFormat instance, to allow for chaining
*/
MessageFormat.prototype.setIntlSupport = function(enable) {
this.intlSupport = !!enable || (typeof enable == 'undefined');
return this;
};
/** According to the ICU MessageFormat spec, a `#` character directly inside a
* `plural` or `selectordinal` statement should be replaced by the number
* matching the surrounding statement. By default, messageformat.js will
* replace `#` signs with the value of the nearest surrounding `plural` or
* `selectordinal` statement.
*
* Set this to true to follow the stricter ICU MessageFormat spec, and to
* throw a runtime error if `#` is used with non-numeric input.
*
* @memberof MessageFormat
* @param {boolean} [enable=true]
* @returns {MessageFormat} The MessageFormat instance, to allow for chaining
*
* @example
* var mf = new MessageFormat('en');
*
* var cookieMsg = '#: {X, plural, =0{no cookies} one{a cookie} other{# cookies}}';
* mf.compile(cookieMsg)({ X: 3 });
* // '#: 3 cookies'
*
* var pastryMsg = '{X, plural, one{{P, select, cookie{a cookie} other{a pie}}} other{{P, select, cookie{# cookies} other{# pies}}}}';
* mf.compile(pastryMsg)({ X: 3, P: 'pie' });
* // '3 pies'
*
* mf.setStrictNumberSign(true);
* mf.compile(pastryMsg)({ X: 3, P: 'pie' });
* // '# pies'
*/
MessageFormat.prototype.setStrictNumberSign = function(enable) {
this.strictNumberSign = !!enable || (typeof enable == 'undefined');
this.runtime.setStrictNumber(this.strictNumberSign);
return this;
};
/** Compile messages into storable functions
*
* If `messages` is a single string including ICU MessageFormat declarations,
* the result of `compile()` is a function taking a single Object parameter
* `d` representing each of the input's defined variables.
*
* If `messages` is a hierarchical structure of such strings, the output of
* `compile()` will match that structure, with each string replaced by its
* corresponding JavaScript function.
*
* If the input `messages` -- and therefore the output -- of `compile()` is an
* object, the output object will have a `toString(global)` method that may be
* used to store or cache the compiled functions to disk, for later inclusion
* in any JS environment, without a local MessageFormat instance required. Its
* `global` parameters sets the name (if any) of the resulting global variable,
* with special handling for `exports`, `module.exports`, and `export default`.
* If `global` does not contain a `.`, the output defaults to an UMD pattern.
*
* If `locale` is not set, the first locale set in the object's constructor
* will be used by default; using a key at any depth of `messages` that is a
* declared locale will set its child elements to use that locale.
*
* If `locale` is set, it is used for all messages. If the constructor
* declared any locales, `locale` needs to be one of them.
*
* @memberof MessageFormat
* @param {string|Object} messages - The input message(s) to be compiled, in ICU MessageFormat
* @param {string} [locale] - A locale to use for the messages
* @returns {function|Object} The first match found for the given locale(s)
*
* @example
* var mf = new MessageFormat('en');
* var cf = mf.compile('A {TYPE} example.');
*
* cf({ TYPE: 'simple' })
* // 'A simple example.'
*
* @example
* var mf = new MessageFormat(['en', 'fi']);
* var cf = mf.compile({
* en: { a: 'A {TYPE} example.',
* b: 'This is the {COUNT, selectordinal, one{#st} two{#nd} few{#rd} other{#th}} example.' },
* fi: { a: '{TYPE} esimerkki.',
* b: 'Tämä on {COUNT, selectordinal, other{#.}} esimerkki.' }
* });
*
* cf.en.b({ COUNT: 2 })
* // 'This is the 2nd example.'
*
* cf.fi.b({ COUNT: 2 })
* // 'Tämä on 2. esimerkki.'
*
* @example
* var fs = require('fs');
* var mf = new MessageFormat('en').setIntlSupport();
* var msgSet = {
* a: 'A {TYPE} example.',
* b: 'This has {COUNT, plural, one{one member} other{# members}}.',
* c: 'We have {P, number, percent} code coverage.'
* };
* var cfStr = mf.compile(msgSet).toString('module.exports');
* fs.writeFileSync('messages.js', cfStr);
* ...
* var messages = require('./messages');
*
* messages.a({ TYPE: 'more complex' })
* // 'A more complex example.'
*
* messages.b({ COUNT: 3 })
* // 'This has 3 members.'
*/
MessageFormat.prototype.compile = function(messages, locale) {
function _stringify(obj, level) {
if (!level) level = 0;
if (typeof obj != 'object') return obj;
var o = [], indent = '';
for (var i = 0; i < level; ++i) indent += ' ';
for (var k in obj) o.push('\n' + indent + ' ' + Compiler.propname(k) + ': ' + _stringify(obj[k], level + 1));
return '{' + o.join(',') + '\n' + indent + '}';
}
var pf;
if (Object.keys(this.pluralFuncs).length == 0) {
if (!locale) locale = MessageFormat.defaultLocale;
pf = {};
pf[locale] = getPluralFunc(locale, this.noPluralKeyChecks);
} else if (locale) {
pf = {};
pf[locale] = this.pluralFuncs[locale];
if (!pf[locale]) throw new Error('Locale ' + JSON.stringify(locale) + 'not found in ' + JSON.stringify(this.pluralFuncs) + '!');
} else {
pf = this.pluralFuncs;
locale = Object.keys(pf)[0];
}
var compiler = new Compiler(this);
var obj = compiler.compile(messages, locale, pf);
if (typeof messages != 'object') {
var fn = new Function(
'number, plural, select, fmt', Compiler.funcname(locale),
'return ' + obj);
var rt = this.runtime;
return fn(rt.number, rt.plural, rt.select, this.fmt, pf[locale]);
}
var rtStr = this.runtime.toString(pf, compiler) + '\n';
var objStr = _stringify(obj);
var result = new Function(rtStr + 'return ' + objStr)();
if (result.hasOwnProperty('toString')) throw new Error('The top-level message key `toString` is reserved');
result.toString = function(global) {
switch (global || '') {
case 'exports':
var o = [];
for (var k in obj) o.push(Compiler.propname(k, 'exports') + ' = ' + _stringify(obj[k]));
return rtStr + o.join(';\n');
case 'module.exports':
return rtStr + 'module.exports = ' + objStr;
case 'export default':
return rtStr + 'export default ' + objStr;
case '':
return rtStr + 'return ' + objStr;
default:
if (global.indexOf('.') > -1) return rtStr + global + ' = ' + objStr;
return rtStr + [
'(function (root, G) {',
' if (typeof define === "function" && define.amd) { define(G); }',
' else if (typeof exports === "object") { module.exports = G; }',
' else { ' + Compiler.propname(global, 'root') + ' = G; }',
'})(this, ' + objStr + ');'
].join('\n');
}
}
return result;
}
module.exports = MessageFormat;
},{"./compiler":1,"./runtime":3,"make-plural/pluralCategories":6,"make-plural/plurals":7}],3:[function(require,module,exports){
var Compiler = require('./compiler');
/** A set of utility functions that are called by the compiled Javascript
* functions, these are included locally in the output of {@link
* MessageFormat#compile compile()}.
*
* @class
* @param {MessageFormat} mf - A MessageFormat instance
*/
function Runtime(mf) {
this.mf = mf;
this.setStrictNumber(mf.strictNumberSign);
}
module.exports = Runtime;
/** Utility function for `#` in plural rules
*
* Will throw an Error if `value` has a non-numeric value and `offset` is
* non-zero or {@link MessageFormat#setStrictNumberSign} is set.
*
* @function Runtime#number
* @param {number} value - The value to operate on
* @param {string} name - The name of the argument, used for error reporting
* @param {number} [offset=0] - An optional offset, set by the surrounding context
* @returns {number|string} The result of applying the offset to the input value
*/
function defaultNumber(value, name, offset) {
if (!offset) return value;
if (isNaN(value)) throw new Error('Can\'t apply offset:' + offset + ' to argument `' + name +
'` with non-numerical value ' + JSON.stringify(value) + '.');
return value - offset;
}
/** @private */
function strictNumber(value, name, offset) {
if (isNaN(value)) throw new Error('Argument `' + name + '` has non-numerical value ' + JSON.stringify(value) + '.');
return value - (offset || 0);
}
/** Set how strictly the {@link number} method parses its input.
*
* According to the ICU MessageFormat spec, `#` can only be used to replace a
* number input of a `plural` statement. By default, messageformat.js does not
* throw a runtime error if you use non-numeric argument with a `plural` rule,
* unless rule also includes a non-zero `offset`.
*
* This is called by {@link MessageFormat#setStrictNumberSign} to follow the
* stricter ICU MessageFormat spec.
*
* @param {boolean} [enable=false]
*/
Runtime.prototype.setStrictNumber = function(enable) {
this.number = enable ? strictNumber : defaultNumber;
}
/** Utility function for `{N, plural|selectordinal, ...}`
*
* @param {number} value - The key to use to find a pluralization rule
* @param {number} offset - An offset to apply to `value`
* @param {function} lcfunc - A locale function from `pluralFuncs`
* @param {Object.<string,string>} data - The object from which results are looked up
* @param {?boolean} isOrdinal - If true, use ordinal rather than cardinal rules
* @returns {string} The result of the pluralization
*/
Runtime.prototype.plural = function(value, offset, lcfunc, data, isOrdinal) {
if ({}.hasOwnProperty.call(data, value)) return data[value];
if (offset) value -= offset;
var key = lcfunc(value, isOrdinal);
if (key in data) return data[key];
return data.other;
}
/** Utility function for `{N, select, ...}`
*
* @param {number} value - The key to use to find a selection
* @param {Object.<string,string>} data - The object from which results are looked up
* @returns {string} The result of the select statement
*/
Runtime.prototype.select = function(value, data) {
if ({}.hasOwnProperty.call(data, value)) return data[value];
return data.other;
}
/** @private */
Runtime.prototype.toString = function(pluralFuncs, compiler) {
function _stringify(o, level) {
if (typeof o != 'object') {
var funcStr = o.toString().replace(/^(function )\w*/, '$1');
var indent = /([ \t]*)\S.*$/.exec(funcStr);
return indent ? funcStr.replace(new RegExp('^' + indent[1], 'mg'), '') : funcStr;
}
var s = [];
for (var i in o) {
if (level == 0) s.push('var ' + i + ' = ' + _stringify(o[i], level + 1) + ';\n');
else s.push(Compiler.propname(i) + ': ' + _stringify(o[i], level + 1));
}
if (level == 0) return s.join('');
if (s.length == 0) return '{}';
var indent = ' '; while (--level) indent += ' ';
return '{\n' + s.join(',\n').replace(/^/gm, indent) + '\n}';
}
var obj = {};
Object.keys(compiler.locales).forEach(function(lc) { obj[Compiler.funcname(lc)] = pluralFuncs[lc]; });
Object.keys(compiler.runtime).forEach(function(fn) { obj[fn] = this[fn]; }, this);
var fmtKeys = Object.keys(compiler.formatters);
var fmt = this.mf.fmt;
if (fmtKeys.length) obj.fmt = fmtKeys.reduce(function(o, key) { o[key] = fmt[key]; return o; }, {});
return _stringify(obj, 0);
}
},{"./compiler":1}],4:[function(require,module,exports){
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
//
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
//
// Originally from narwhal.js (http://narwhaljs.org)
// Copyright (c) 2009 Thomas Robinson <280north.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the 'Software'), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// when used in node, this will actually load the util module we depend on
// versus loading the builtin util module as happens otherwise
// this is a bug in node module loading as far as I am concerned
var util = require('util/');
var pSlice = Array.prototype.slice;
var hasOwn = Object.prototype.hasOwnProperty;
// 1. The assert module provides functions that throw
// AssertionError's when particular conditions are not met. The
// assert module must conform to the following interface.
var assert = module.exports = ok;
// 2. The AssertionError is defined in assert.
// new assert.AssertionError({ message: message,
// actual: actual,
// expected: expected })
assert.AssertionError = function AssertionError(options) {
this.name = 'AssertionError';
this.actual = options.actual;
this.expected = options.expected;
this.operator = options.operator;
if (options.message) {
this.message = options.message;
this.generatedMessage = false;
} else {
this.message = getMessage(this);
this.generatedMessage = true;
}
var stackStartFunction = options.stackStartFunction || fail;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, stackStartFunction);
}
else {
// non v8 browsers so we can have a stacktrace
var err = new Error();
if (err.stack) {
var out = err.stack;
// try to strip useless frames
var fn_name = stackStartFunction.name;
var idx = out.indexOf('\n' + fn_name);
if (idx >= 0) {
// once we have located the function frame
// we need to strip out everything before it (and its line)
var next_line = out.indexOf('\n', idx + 1);
out = out.substring(next_line + 1);
}
this.stack = out;
}
}
};
// assert.AssertionError instanceof Error
util.inherits(assert.AssertionError, Error);
function replacer(key, value) {
if (util.isUndefined(value)) {
return '' + value;
}
if (util.isNumber(value) && !isFinite(value)) {
return value.toString();
}
if (util.isFunction(value) || util.isRegExp(value)) {
return value.toString();
}
return value;
}
function truncate(s, n) {
if (util.isString(s)) {
return s.length < n ? s : s.slice(0, n);
} else {
return s;
}
}
function getMessage(self) {
return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
self.operator + ' ' +
truncate(JSON.stringify(self.expected, replacer), 128);
}
// At present only the three keys mentioned above are used and
// understood by the spec. Implementations or sub modules can pass
// other keys to the AssertionError's constructor - they will be
// ignored.
// 3. All of the following functions must throw an AssertionError
// when a corresponding condition is not met, with a message that
// may be undefined if not provided. All assertion methods provide
// both the actual and expected values to the assertion error for
// display purposes.
function fail(actual, expected, message, operator, stackStartFunction) {
throw new assert.AssertionError({
message: message,
actual: actual,
expected: expected,
operator: operator,
stackStartFunction: stackStartFunction
});
}
// EXTENSION! allows for well behaved errors defined elsewhere.
assert.fail = fail;
// 4. Pure assertion tests whether a value is truthy, as determined
// by !!guard.
// assert.ok(guard, message_opt);
// This statement is equivalent to assert.equal(true, !!guard,
// message_opt);. To test strictly for the value true, use
// assert.strictEqual(true, guard, message_opt);.
function ok(value, message) {
if (!value) fail(value, true, message, '==', assert.ok);
}
assert.ok = ok;
// 5. The equality assertion tests shallow, coercive equality with
// ==.
// assert.equal(actual, expected, message_opt);
assert.equal = function equal(actual, expected, message) {
if (actual != expected) fail(actual, expected, message, '==', assert.equal);
};
// 6. The non-equality assertion tests for whether two objects are not equal
// with != assert.notEqual(actual, expected, message_opt);
assert.notEqual = function notEqual(actual, expected, message) {
if (actual == expected) {
fail(actual, expected, message, '!=', assert.notEqual);
}
};
// 7. The equivalence assertion tests a deep equality relation.
// assert.deepEqual(actual, expected, message_opt);
assert.deepEqual = function deepEqual(actual, expected, message) {
if (!_deepEqual(actual, expected)) {
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
}
};
function _deepEqual(actual, expected) {
// 7.1. All identical values are equivalent, as determined by ===.
if (actual === expected) {
return true;
} else if (util.isBuffer(actual) && util.isBuffer(expected)) {
if (actual.length != expected.length) return false;
for (var i = 0; i < actual.length; i++) {
if (actual[i] !== expected[i]) return false;
}
return true;
// 7.2. If the expected value is a Date object, the actual value is
// equivalent if it is also a Date object that refers to the same time.
} else if (util.isDate(actual) && util.isDate(expected)) {
return actual.getTime() === expected.getTime();
// 7.3 If the expected value is a RegExp object, the actual value is
// equivalent if it is also a RegExp object with the same source and
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
} else if (util.isRegExp(actual) && util.isRegExp(expected)) {
return actual.source === expected.source &&
actual.global === expected.global &&
actual.multiline === expected.multiline &&
actual.lastIndex === expected.lastIndex &&
actual.ignoreCase === expected.ignoreCase;
// 7.4. Other pairs that do not both pass typeof value == 'object',
// equivalence is determined by ==.
} else if (!util.isObject(actual) && !util.isObject(expected)) {
return actual == expected;
// 7.5 For all other Object pairs, including Array objects, equivalence is
// determined by having the same number of owned properties (as verified
// with Object.prototype.hasOwnProperty.call), the same set of keys
// (although not necessarily the same order), equivalent values for every
// corresponding key, and an identical 'prototype' property. Note: this
// accounts for both named and indexed properties on Arrays.
} else {
return objEquiv(actual, expected);
}
}
function isArguments(object) {
return Object.prototype.toString.call(object) == '[object Arguments]';
}
function objEquiv(a, b) {
if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
return false;
// an identical 'prototype' property.
if (a.prototype !== b.prototype) return false;
// if one is a primitive, the other must be same
if (util.isPrimitive(a) || util.isPrimitive(b)) {
return a === b;
}
var aIsArgs = isArguments(a),
bIsArgs = isArguments(b);
if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))
return false;
if (aIsArgs) {
a = pSlice.call(a);
b = pSlice.call(b);
return _deepEqual(a, b);
}
var ka = objectKeys(a),
kb = objectKeys(b),
key, i;
// having the same number of owned properties (keys incorporates
// hasOwnProperty)
if (ka.length != kb.length)
return false;
//the same set of keys (although not necessarily the same order),
ka.sort();
kb.sort();
//~~~cheap key test
for (i = ka.length - 1; i >= 0; i--) {
if (ka[i] != kb[i])
return false;
}
//equivalent values for every corresponding key, and
//~~~possibly expensive deep test
for (i = ka.length - 1; i >= 0; i--) {
key = ka[i];
if (!_deepEqual(a[key], b[key])) return false;
}
return true;
}
// 8. The non-equivalence assertion tests for any deep inequality.
// assert.notDeepEqual(actual, expected, message_opt);
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
if (_deepEqual(actual, expected)) {
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
}
};
// 9. The strict equality assertion tests strict equality, as determined by ===.
// assert.strictEqual(actual, expected, message_opt);
assert.strictEqual = function strictEqual(actual, expected, message) {
if (actual !== expected) {
fail(actual, expected, message, '===', assert.strictEqual);
}
};
// 10. The strict non-equality assertion tests for strict inequality, as
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
if (actual === expected) {
fail(actual, expected, message, '!==', assert.notStrictEqual);
}
};
function expectedException(actual, expected) {
if (!actual || !expected) {
return false;
}
if (Object.prototype.toString.call(expected) == '[object RegExp]') {
return expected.test(actual);
} else if (actual instanceof expected) {
return true;
} else if (expected.call({}, actual) === true) {
return true;
}
return false;
}
function _throws(shouldThrow, block, expected, message) {
var actual;
if (util.isString(expected)) {
message = expected;
expected = null;
}
try {
block();
} catch (e) {
actual = e;
}
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
(message ? ' ' + message : '.');
if (shouldThrow && !actual) {
fail(actual, expected, 'Missing expected exception' + message);
}
if (!shouldThrow && expectedException(actual, expected)) {
fail(actual, expected, 'Got unwanted exception' + message);
}
if ((shouldThrow && actual && expected &&
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
throw actual;
}
}
// 11. Expected to throw an error:
// assert.throws(block, Error_opt, message_opt);
assert.throws = function(block, /*optional*/error, /*optional*/message) {
_throws.apply(this, [true].concat(pSlice.call(arguments)));
};
// EXTENSION! This is annoying to write outside this module.
assert.doesNotThrow = function(block, /*optional*/message) {
_throws.apply(this, [false].concat(pSlice.call(arguments)));
};
assert.ifError = function(err) { if (err) {throw err;}};
var objectKeys = Object.keys || function (obj) {
var keys = [];
for (var key in obj) {
if (hasOwn.call(obj, key)) keys.push(key);
}
return keys;
};
},{"util/":13}],5:[function(require,module,exports){
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
} else {
// old school shim for old browsers
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
var TempCtor = function () {}
TempCtor.prototype = superCtor.prototype
ctor.prototype = new TempCtor()
ctor.prototype.constructor = ctor
}
}
},{}],6:[function(require,module,exports){
var _cc = [
{cardinal:["other"],ordinal:["other"]},
{cardinal:["one","other"],ordinal:["other"]},
{cardinal:["one","other"],ordinal:["one","other"]},
{cardinal:["one","two","other"],ordinal:["other"]}
];
(function (root, pluralCategories) {
if (typeof define === 'function' && define.amd) {
define(pluralCategories);
} else if (typeof exports === 'object') {
module.exports = pluralCategories;
} else {
root.pluralCategories = pluralCategories;
}
}(this, {
af: _cc[1],
ak: _cc[1],
am: _cc[1],
ar: {cardinal:["zero","one","two","few","many","other"],ordinal:["other"]},
as: {cardinal:["one","other"],ordinal:["one","two","few","many","other"]},
asa: _cc[1],
ast: _cc[1],
az: {cardinal:["one","other"],ordinal:["one","few","many","other"]},
be: {cardinal:["one","few","many","other"],ordinal:["few","other"]},
bem: _cc[1],
bez: _cc[1],
bg: _cc[1],
bh: _cc[1],
bm: _cc[0],
bn: {cardinal:["one","other"],ordinal:["one","two","few","many","other"]},
bo: _cc[0],
br: {cardinal:["one","two","few","many","other"],ordinal:["other"]},
brx: _cc[1],
bs: {cardinal:["one","few","other"],ordinal:["other"]},
ca: {cardinal:["one","other"],ordinal:["one","two","few","other"]},
ce: _cc[1],
cgg: _cc[1],
chr: _cc[1],
ckb: _cc[1],
cs: {cardinal:["one","few","many","other"],ordinal:["other"]},
cy: {cardinal:["zero","one","two","few","many","other"],ordinal:["zero","one","two","few","many","other"]},
da: _cc[1],
de: _cc[1],
dsb: {cardinal:["one","two","few","other"],ordinal:["other"]},
dv: _cc[1],
dz: _cc[0],
ee: _cc[1],
el: _cc[1],
en: {cardinal:["one","other"],ordinal:["one","two","few","other"]},
eo: _cc[1],
es: _cc[1],
et: _cc[1],
eu: _cc[1],
fa: _cc[1],
ff: _cc[1],
fi: _cc[1],
fil: _cc[2],
fo: _cc[1],
fr: _cc[2],
fur: _cc[1],
fy: _cc[1],
ga: {cardinal:["one","two","few","many","other"],ordinal:["one","other"]},
gd: {cardinal:["one","two","few","other"],ordinal:["other"]},
gl: _cc[1],
gsw: _cc[1],
gu: {cardinal:["one","other"],ordinal:["one","two","few","many","other"]},
guw: _cc[1],
gv: {cardinal:["one","two","few","many","other"],ordinal:["other"]},
ha: _cc[1],
haw: _cc[1],
he: {cardinal:["one","two","many","other"],ordinal:["other"]},
hi: {cardinal:["one","other"],ordinal:["one","two","few","many","other"]},
hr: {cardinal:["one","few","other"],ordinal:["other"]},
hsb: {cardinal:["one","two","few","other"],ordinal:["other"]},
hu: _cc[2],
hy: _cc[2],
id: _cc[0],
ig: _cc[0],
ii: _cc[0],
"in": _cc[0],
is: _cc[1],
it: {cardinal:["one","other"],ordinal:["many","other"]},
iu: _cc[3],
iw: {cardinal:["one","two","many","other"],ordinal:["other"]},
ja: _cc[0],
jbo: _cc[0],
jgo: _cc[1],
ji: _cc[1],
jmc: _cc[1],
jv: _cc[0],
jw: _cc[0],
ka: {cardinal:["one","other"],ordinal:["one","many","other"]},
kab: _cc[1],
kaj: _cc[1],
kcg: _cc[1],
kde: _cc[0],
kea: _cc[0],
kk: {cardinal:["one","other"],ordinal:["many","other"]},
kkj: _cc[1],
kl: _cc[1],
km: _cc[0],
kn: _cc[1],
ko: _cc[0],
ks: _cc[1],
ksb: _cc[1],
ksh: {cardinal:["zero","one","other"],ordinal:["other"]},
ku: _cc[1],
kw: _cc[3],
ky: _cc[1],
lag: {cardinal:["zero","one","other"],ordinal:["other"]},
lb: _cc[1],
lg: _cc[1],
lkt: _cc[0],
ln: _cc[1],
lo: {cardinal:["other"],ordinal:["one","other"]},
lt: {cardinal:["one","few","many","other"],ordinal:["other"]},
lv: {cardinal:["zero","one","other"],ordinal:["other"]},
mas: _cc[1],
mg: _cc[1],
mgo: _cc[1],
mk: {cardinal:["one","other"],ordinal:["one","two","many","other"]},
ml: _cc[1],
mn: _cc[1],
mo: {cardinal:["one","few","other"],ordinal:["one","other"]},
mr: {cardinal:["one","other"],ordinal:["one","two","few","other"]},
ms: {cardinal:["other"],ordinal:["one","other"]},
mt: {cardinal:["one","few","many","other"],ordinal:["other"]},
my: _cc[0],
nah: _cc[1],
naq: _cc[3],
nb: _cc[1],
nd: _cc[1],
ne: _cc[2],
nl: _cc[1],
nn: _cc[1],
nnh: _cc[1],
no: _cc[1],
nqo: _cc[0],
nr: _cc[1],
nso: _cc[1],
ny: _cc[1],
nyn: _cc[1],
om: _cc[1],
or: _cc[1],
os: _cc[1],
pa: _cc[1],
pap: _cc[1],
pl: {cardinal:["one","few","many","other"],ordinal:["other"]},
prg: {cardinal:["zero","one","other"],ordinal:["other"]},
ps: _cc[1],
pt: _cc[1],
"pt-PT": _cc[1],
rm: _cc[1],
ro: {cardinal:["one","few","other"],ordinal:["one","other"]},
rof: _cc[1],
root: _cc[0],
ru: {cardinal:["one","few","many","other"],ordinal:["other"]},
rwk: _cc[1],
sah: _cc[0],
saq: _cc[1],
sdh: _cc[1],
se: _cc[3],
seh: _cc[1],
ses: _cc[0],
sg: _cc[0],
sh: {cardinal:["one","few","other"],ordinal:["other"]},
shi: {cardinal:["one","few","other"],ordinal:["other"]},
si: _cc[1],
sk: {cardinal:["one","few","many","other"],ordinal:["other"]},
sl: {cardinal:["one","two","few","other"],ordinal:["other"]},
sma: _cc[3],
smi: _cc[3],
smj: _cc[3],
smn: _cc[3],
sms: _cc[3],
sn: _cc[1],
so: _cc[1],
sq: {cardinal:["one","other"],ordinal:["one","many","other"]},
sr: {cardinal:["one","few","other"],ordinal:["other"]},
ss: _cc[1],
ssy: _cc[1],
st: _cc[1],
sv: _cc[2],
sw: _cc[1],
syr: _cc[1],
ta: _cc[1],
te: _cc[1],
teo: _cc[1],
th: _cc[0],
ti: _cc[1],
tig: _cc[1],
tk: _cc[1],
tl: _cc[2],
tn: _cc[1],
to: _cc[0],
tr: _cc[1],
ts: _cc[1],
tzm: _cc[1],
ug: _cc[1],
uk: {cardinal:["one","few","many","other"],ordinal:["few","other"]},
ur: _cc[1],
uz: _cc[1],
ve: _cc[1],
vi: {cardinal:["other"],ordinal:["one","other"]},
vo: _cc[1],
vun: _cc[1],
wa: _cc[1],
wae: _cc[1],
wo: _cc[0],
xh: _cc[1],
xog: _cc[1],
yi: _cc[1],
yo: _cc[0],
zh: _cc[0],
zu: _cc[1]
}));
},{}],7:[function(require,module,exports){
var _cp = [
function(n, ord) {
if (ord) return 'other';
return 'other';
},
function(n, ord) {
if (ord) return 'other';
return (n == 1) ? 'one' : 'other';
},
function(n, ord) {
if (ord) return 'other';
return ((n == 0
|| n == 1)) ? 'one' : 'other';
},
function(n, ord) {
var s = String(n).split('.'), v0 = !s[1];
if (ord) return 'other';
return (n == 1 && v0) ? 'one' : 'other';
}
];
(function (root, plurals) {
if (typeof define === 'function' && define.amd) {
define(plurals);
} else if (typeof exports === 'object') {
module.exports = plurals;
} else {
root.plurals = plurals;
}
}(this, {
af: _cp[1],
ak: _cp[2],
am: function(n, ord) {
if (ord) return 'other';
return (n >= 0 && n <= 1) ? 'one' : 'other';
},
ar: function(n, ord) {
var s = String(n).split('.'), t0 = Number(s[0]) == n,
n100 = t0 && s[0].slice(-2);
if (ord) return 'other';
return (n == 0) ? 'zero'
: (n == 1) ? 'one'
: (n == 2) ? 'two'
: ((n100 >= 3 && n100 <= 10)) ? 'few'
: ((n100 >= 11 && n100 <= 99)) ? 'many'
: 'other';
},
as: function(n, ord) {
if (ord) return ((n == 1 || n == 5 || n == 7 || n == 8 || n == 9
|| n == 10)) ? 'one'
: ((n == 2
|| n == 3)) ? 'two'
: (n == 4) ? 'few'
: (n == 6) ? 'many'
: 'other';
return (n >= 0 && n <= 1) ? 'one' : 'other';
},
asa: _cp[1],
ast: _cp[3],
az: function(n, ord) {
var s = String(n).split('.'), i = s[0], i10 = i.slice(-1),
i100 = i.slice(-2), i1000 = i.slice(-3);
if (ord) return ((i10 == 1 || i10 == 2 || i10 == 5 |