Repository: incubator-guacamole-client Updated Branches: refs/heads/master 047c77592 -> 4e788d6ad
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/9387961c/guacamole/src/main/webapp/lib/messageformat/messageformat.js ---------------------------------------------------------------------- diff --git a/guacamole/src/main/webapp/lib/messageformat/messageformat.js b/guacamole/src/main/webapp/lib/messageformat/messageformat.js index b8ba9e3..5949f5e 100644 --- a/guacamole/src/main/webapp/lib/messageformat/messageformat.js +++ b/guacamole/src/main/webapp/lib/messageformat/messageformat.js @@ -1,1593 +1,4755 @@ -/** - * messageformat.js +(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. * - * ICU PluralFormat + SelectFormat for JavaScript + * 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 || i10 == 7 || i10 == 8) + || (i100 == 20 || i100 == 50 || i100 == 70 + || i100 == 80)) ? 'one' + : ((i10 == 3 || i10 == 4) || (i1000 == 100 || i1000 == 200 + || i1000 == 300 || i1000 == 400 || i1000 == 500 || i1000 == 600 || i1000 == 700 + || i1000 == 800 + || i1000 == 900)) ? 'few' + : (i == 0 || i10 == 6 || (i100 == 40 || i100 == 60 + || i100 == 90)) ? 'many' + : 'other'; + return (n == 1) ? 'one' : 'other'; +}, + +be: function(n, ord) { + var s = String(n).split('.'), t0 = Number(s[0]) == n, + n10 = t0 && s[0].slice(-1), n100 = t0 && s[0].slice(-2); + if (ord) return ((n10 == 2 + || n10 == 3) && n100 != 12 && n100 != 13) ? 'few' : 'other'; + return (n10 == 1 && n100 != 11) ? 'one' + : ((n10 >= 2 && n10 <= 4) && (n100 < 12 + || n100 > 14)) ? 'few' + : (t0 && n10 == 0 || (n10 >= 5 && n10 <= 9) + || (n100 >= 11 && n100 <= 14)) ? 'many' + : 'other'; +}, + +bem: _cp[1], + +bez: _cp[1], + +bg: _cp[1], + +bh: _cp[2], + +bm: _cp[0], + +bn: 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'; +}, + +bo: _cp[0], + +br: function(n, ord) { + var s = String(n).split('.'), t0 = Number(s[0]) == n, + n10 = t0 && s[0].slice(-1), n100 = t0 && s[0].slice(-2), + n1000000 = t0 && s[0].slice(-6); + if (ord) return 'other'; + return (n10 == 1 && n100 != 11 && n100 != 71 && n100 != 91) ? 'one' + : (n10 == 2 && n100 != 12 && n100 != 72 && n100 != 92) ? 'two' + : (((n10 == 3 || n10 == 4) || n10 == 9) && (n100 < 10 + || n100 > 19) && (n100 < 70 || n100 > 79) && (n100 < 90 + || n100 > 99)) ? 'few' + : (n != 0 && t0 && n1000000 == 0) ? 'many' + : 'other'; +}, + +brx: _cp[1], + +bs: function(n, ord) { + var s = String(n).split('.'), i = s[0], f = s[1] || '', v0 = !s[1], + i10 = i.slice(-1), i100 = i.slice(-2), f10 = f.slice(-1), f100 = f.slice(-2); + if (ord) return 'other'; + return (v0 && i10 == 1 && i100 != 11 + || f10 == 1 && f100 != 11) ? 'one' + : (v0 && (i10 >= 2 && i10 <= 4) && (i100 < 12 || i100 > 14) + || (f10 >= 2 && f10 <= 4) && (f100 < 12 + || f100 > 14)) ? 'few' + : 'other'; +}, + +ca: function(n, ord) { + var s = String(n).split('.'), v0 = !s[1]; + if (ord) return ((n == 1 + || n == 3)) ? 'one' + : (n == 2) ? 'two' + : (n == 4) ? 'few' + : 'other'; + return (n == 1 && v0) ? 'one' : 'other'; +}, + +ce: _cp[1], + +cgg: _cp[1], + +chr: _cp[1], + +ckb: _cp[1], + +cs: function(n, ord) { + var s = String(n).split('.'), i = s[0], v0 = !s[1]; + if (ord) return 'other'; + return (n == 1 && v0) ? 'one' + : ((i >= 2 && i <= 4) && v0) ? 'few' + : (!v0) ? 'many' + : 'other'; +}, + +cy: function(n, ord) { + if (ord) return ((n == 0 || n == 7 || n == 8 + || n == 9)) ? 'zero' + : (n == 1) ? 'one' + : (n == 2) ? 'two' + : ((n == 3 + || n == 4)) ? 'few' + : ((n == 5 + || n == 6)) ? 'many' + : 'other'; + return (n == 0) ? 'zero' + : (n == 1) ? 'one' + : (n == 2) ? 'two' + : (n == 3) ? 'few' + : (n == 6) ? 'many' + : 'other'; +}, + +da: function(n, ord) { + var s = String(n).split('.'), i = s[0], t0 = Number(s[0]) == n; + if (ord) return 'other'; + return (n == 1 || !t0 && (i == 0 + || i == 1)) ? 'one' : 'other'; +}, + +de: _cp[3], + +dsb: function(n, ord) { + var s = String(n).split('.'), i = s[0], f = s[1] || '', v0 = !s[1], + i100 = i.slice(-2), f100 = f.slice(-2); + if (ord) return 'other'; + return (v0 && i100 == 1 + || f100 == 1) ? 'one' + : (v0 && i100 == 2 + || f100 == 2) ? 'two' + : (v0 && (i100 == 3 || i100 == 4) || (f100 == 3 + || f100 == 4)) ? 'few' + : 'other'; +}, + +dv: _cp[1], + +dz: _cp[0], + +ee: _cp[1], + +el: _cp[1], + +en: function(n, ord) { + var s = String(n).split('.'), v0 = !s[1], t0 = Number(s[0]) == n, + n10 = t0 && s[0].slice(-1), n100 = t0 && s[0].slice(-2); + if (ord) return (n10 == 1 && n100 != 11) ? 'one' + : (n10 == 2 && n100 != 12) ? 'two' + : (n10 == 3 && n100 != 13) ? 'few' + : 'other'; + return (n == 1 && v0) ? 'one' : 'other'; +}, + +eo: _cp[1], + +es: _cp[1], + +et: _cp[3], + +eu: _cp[1], + +fa: function(n, ord) { + if (ord) return 'other'; + return (n >= 0 && n <= 1) ? 'one' : 'other'; +}, + +ff: function(n, ord) { + if (ord) return 'other'; + return (n >= 0 && n < 2) ? 'one' : 'other'; +}, + +fi: _cp[3], + +fil: function(n, ord) { + var s = String(n).split('.'), i = s[0], f = s[1] || '', v0 = !s[1], + i10 = i.slice(-1), f10 = f.slice(-1); + if (ord) return (n == 1) ? 'one' : 'other'; + return (v0 && (i == 1 || i == 2 || i == 3) + || v0 && i10 != 4 && i10 != 6 && i10 != 9 + || !v0 && f10 != 4 && f10 != 6 && f10 != 9) ? 'one' : 'other'; +}, + +fo: _cp[1], + +fr: function(n, ord) { + if (ord) return (n == 1) ? 'one' : 'other'; + return (n >= 0 && n < 2) ? 'one' : 'other'; +}, + +fur: _cp[1], + +fy: _cp[3], + +ga: function(n, ord) { + var s = String(n).split('.'), t0 = Number(s[0]) == n; + if (ord) return (n == 1) ? 'one' : 'other'; + return (n == 1) ? 'one' + : (n == 2) ? 'two' + : ((t0 && n >= 3 && n <= 6)) ? 'few' + : ((t0 && n >= 7 && n <= 10)) ? 'many' + : 'other'; +}, + +gd: function(n, ord) { + var s = String(n).split('.'), t0 = Number(s[0]) == n; + if (ord) return 'other'; + return ((n == 1 + || n == 11)) ? 'one' + : ((n == 2 + || n == 12)) ? 'two' + : (((t0 && n >= 3 && n <= 10) + || (t0 && n >= 13 && n <= 19))) ? 'few' + : 'other'; +}, + +gl: _cp[3], + +gsw: _cp[1], + +gu: function(n, ord) { + if (ord) return (n == 1) ? 'one' + : ((n == 2 + || n == 3)) ? 'two' + : (n == 4) ? 'few' + : (n == 6) ? 'many' + : 'other'; + return (n >= 0 && n <= 1) ? 'one' : 'other'; +}, + +guw: _cp[2], + +gv: function(n, ord) { + var s = String(n).split('.'), i = s[0], v0 = !s[1], i10 = i.slice(-1), + i100 = i.slice(-2); + if (ord) return 'other'; + return (v0 && i10 == 1) ? 'one' + : (v0 && i10 == 2) ? 'two' + : (v0 && (i100 == 0 || i100 == 20 || i100 == 40 || i100 == 60 + || i100 == 80)) ? 'few' + : (!v0) ? 'many' + : 'other'; +}, + +ha: _cp[1], + +haw: _cp[1], + +he: function(n, ord) { + var s = String(n).split('.'), i = s[0], v0 = !s[1], t0 = Number(s[0]) == n, + n10 = t0 && s[0].slice(-1); + if (ord) return 'other'; + return (n == 1 && v0) ? 'one' + : (i == 2 && v0) ? 'two' + : (v0 && (n < 0 + || n > 10) && t0 && n10 == 0) ? 'many' + : 'other'; +}, + +hi: function(n, ord) { + if (ord) return (n == 1) ? 'one' + : ((n == 2 + || n == 3)) ? 'two' + : (n == 4) ? 'few' + : (n == 6) ? 'many' + : 'other'; + return (n >= 0 && n <= 1) ? 'one' : 'other'; +}, + +hr: function(n, ord) { + var s = String(n).split('.'), i = s[0], f = s[1] || '', v0 = !s[1], + i10 = i.slice(-1), i100 = i.slice(-2), f10 = f.slice(-1), f100 = f.slice(-2); + if (ord) return 'other'; + return (v0 && i10 == 1 && i100 != 11 + || f10 == 1 && f100 != 11) ? 'one' + : (v0 && (i10 >= 2 && i10 <= 4) && (i100 < 12 || i100 > 14) + || (f10 >= 2 && f10 <= 4) && (f100 < 12 + || f100 > 14)) ? 'few' + : 'other'; +}, + +hsb: function(n, ord) { + var s = String(n).split('.'), i = s[0], f = s[1] || '', v0 = !s[1], + i100 = i.slice(-2), f100 = f.slice(-2); + if (ord) return 'other'; + return (v0 && i100 == 1 + || f100 == 1) ? 'one' + : (v0 && i100 == 2 + || f100 == 2) ? 'two' + : (v0 && (i100 == 3 || i100 == 4) || (f100 == 3 + || f100 == 4)) ? 'few' + : 'other'; +}, + +hu: function(n, ord) { + if (ord) return ((n == 1 + || n == 5)) ? 'one' : 'other'; + return (n == 1) ? 'one' : 'other'; +}, + +hy: function(n, ord) { + if (ord) return (n == 1) ? 'one' : 'other'; + return (n >= 0 && n < 2) ? 'one' : 'other'; +}, + +id: _cp[0], + +ig: _cp[0], + +ii: _cp[0], + +"in": _cp[0], + +is: function(n, ord) { + var s = String(n).split('.'), i = s[0], t0 = Number(s[0]) == n, + i10 = i.slice(-1), i100 = i.slice(-2); + if (ord) return 'other'; + return (t0 && i10 == 1 && i100 != 11 + || !t0) ? 'one' : 'other'; +}, + +it: function(n, ord) { + var s = String(n).split('.'), v0 = !s[1]; + if (ord) return ((n == 11 || n == 8 || n == 80 + || n == 800)) ? 'many' : 'other'; + return (n == 1 && v0) ? 'one' : 'other'; +}, + +iu: function(n, ord) { + if (ord) return 'other'; + return (n == 1) ? 'one' + : (n == 2) ? 'two' + : 'other'; +}, + +iw: function(n, ord) { + var s = String(n).split('.'), i = s[0], v0 = !s[1], t0 = Number(s[0]) == n, + n10 = t0 && s[0].slice(-1); + if (ord) return 'other'; + return (n == 1 && v0) ? 'one' + : (i == 2 && v0) ? 'two' + : (v0 && (n < 0 + || n > 10) && t0 && n10 == 0) ? 'many' + : 'other'; +}, + +ja: _cp[0], + +jbo: _cp[0], + +jgo: _cp[1], + +ji: _cp[3], + +jmc: _cp[1], + +jv: _cp[0], + +jw: _cp[0], + +ka: function(n, ord) { + var s = String(n).split('.'), i = s[0], i100 = i.slice(-2); + if (ord) return (i == 1) ? 'one' + : (i == 0 || ((i100 >= 2 && i100 <= 20) || i100 == 40 || i100 == 60 + || i100 == 80)) ? 'many' + : 'other'; + return (n == 1) ? 'one' : 'other'; +}, + +kab: function(n, ord) { + if (ord) return 'other'; + return (n >= 0 && n < 2) ? 'one' : 'other'; +}, + +kaj: _cp[1], + +kcg: _cp[1], + +kde: _cp[0], + +kea: _cp[0], + +kk: function(n, ord) { + var s = String(n).split('.'), t0 = Number(s[0]) == n, + n10 = t0 && s[0].slice(-1); + if (ord) return (n10 == 6 || n10 == 9 + || t0 && n10 == 0 && n != 0) ? 'many' : 'other'; + return (n == 1) ? 'one' : 'other'; +}, + +kkj: _cp[1], + +kl: _cp[1], + +km: _cp[0], + +kn: function(n, ord) { + if (ord) return 'other'; + return (n >= 0 && n <= 1) ? 'one' : 'other'; +}, + +ko: _cp[0], + +ks: _cp[1], + +ksb: _cp[1], + +ksh: function(n, ord) { + if (ord) return 'other'; + return (n == 0) ? 'zero' + : (n == 1) ? 'one' + : 'other'; +}, + +ku: _cp[1], + +kw: function(n, ord) { + if (ord) return 'other'; + return (n == 1) ? 'one' + : (n == 2) ? 'two' + : 'other'; +}, + +ky: _cp[1], + +lag: function(n, ord) { + var s = String(n).split('.'), i = s[0]; + if (ord) return 'other'; + return (n == 0) ? 'zero' + : ((i == 0 + || i == 1) && n != 0) ? 'one' + : 'other'; +}, + +lb: _cp[1], + +lg: _cp[1], + +lkt: _cp[0], + +ln: _cp[2], + +lo: function(n, ord) { + if (ord) return (n == 1) ? 'one' : 'other'; + return 'other'; +}, + +lt: function(n, ord) { + var s = String(n).split('.'), f = s[1] || '', t0 = Number(s[0]) == n, + n10 = t0 && s[0].slice(-1), n100 = t0 && s[0].slice(-2); + if (ord) return 'other'; + return (n10 == 1 && (n100 < 11 + || n100 > 19)) ? 'one' + : ((n10 >= 2 && n10 <= 9) && (n100 < 11 + || n100 > 19)) ? 'few' + : (f != 0) ? 'many' + : 'other'; +}, + +lv: function(n, ord) { + var s = String(n).split('.'), f = s[1] || '', v = f.length, + t0 = Number(s[0]) == n, n10 = t0 && s[0].slice(-1), + n100 = t0 && s[0].slice(-2), f100 = f.slice(-2), f10 = f.slice(-1); + if (ord) return 'other'; + return (t0 && n10 == 0 || (n100 >= 11 && n100 <= 19) + || v == 2 && (f100 >= 11 && f100 <= 19)) ? 'zero' + : (n10 == 1 && n100 != 11 || v == 2 && f10 == 1 && f100 != 11 + || v != 2 && f10 == 1) ? 'one' + : 'other'; +}, + +mas: _cp[1], + +mg: _cp[2], + +mgo: _cp[1], + +mk: function(n, ord) { + var s = String(n).split('.'), i = s[0], f = s[1] || '', v0 = !s[1], + i10 = i.slice(-1), i100 = i.slice(-2), f10 = f.slice(-1); + if (ord) return (i10 == 1 && i100 != 11) ? 'one' + : (i10 == 2 && i100 != 12) ? 'two' + : ((i10 == 7 + || i10 == 8) && i100 != 17 && i100 != 18) ? 'many' + : 'other'; + return (v0 && i10 == 1 + || f10 == 1) ? 'one' : 'other'; +}, + +ml: _cp[1], + +mn: _cp[1], + +mo: function(n, ord) { + var s = String(n).split('.'), v0 = !s[1], t0 = Number(s[0]) == n, + n100 = t0 && s[0].slice(-2); + if (ord) return (n == 1) ? 'one' : 'other'; + return (n == 1 && v0) ? 'one' + : (!v0 || n == 0 + || n != 1 && (n100 >= 1 && n100 <= 19)) ? 'few' + : 'other'; +}, + +mr: function(n, ord) { + if (ord) return (n == 1) ? 'one' + : ((n == 2 + || n == 3)) ? 'two' + : (n == 4) ? 'few' + : 'other'; + return (n >= 0 && n <= 1) ? 'one' : 'other'; +}, + +ms: function(n, ord) { + if (ord) return (n == 1) ? 'one' : 'other'; + return 'other'; +}, + +mt: 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 == 1) ? 'one' + : (n == 0 + || (n100 >= 2 && n100 <= 10)) ? 'few' + : ((n100 >= 11 && n100 <= 19)) ? 'many' + : 'other'; +}, + +my: _cp[0], + +nah: _cp[1], + +naq: function(n, ord) { + if (ord) return 'other'; + return (n == 1) ? 'one' + : (n == 2) ? 'two' + : 'other'; +}, + +nb: _cp[1], + +nd: _cp[1], + +ne: function(n, ord) { + var s = String(n).split('.'), t0 = Number(s[0]) == n; + if (ord) return ((t0 && n >= 1 && n <= 4)) ? 'one' : 'other'; + return (n == 1) ? 'one' : 'other'; +}, + +nl: _cp[3], + +nn: _cp[1], + +nnh: _cp[1], + +no: _cp[1], + +nqo: _cp[0], + +nr: _cp[1], + +nso: _cp[2], + +ny: _cp[1], + +nyn: _cp[1], + +om: _cp[1], + +or: _cp[1], + +os: _cp[1], + +pa: _cp[2], + +pap: _cp[1], + +pl: function(n, ord) { + var s = String(n).split('.'), i = s[0], v0 = !s[1], i10 = i.slice(-1), + i100 = i.slice(-2); + if (ord) return 'other'; + return (n == 1 && v0) ? 'one' + : (v0 && (i10 >= 2 && i10 <= 4) && (i100 < 12 + || i100 > 14)) ? 'few' + : (v0 && i != 1 && (i10 == 0 || i10 == 1) + || v0 && (i10 >= 5 && i10 <= 9) + || v0 && (i100 >= 12 && i100 <= 14)) ? 'many' + : 'other'; +}, + +prg: function(n, ord) { + var s = String(n).split('.'), f = s[1] || '', v = f.length, + t0 = Number(s[0]) == n, n10 = t0 && s[0].slice(-1), + n100 = t0 && s[0].slice(-2), f100 = f.slice(-2), f10 = f.slice(-1); + if (ord) return 'other'; + return (t0 && n10 == 0 || (n100 >= 11 && n100 <= 19) + || v == 2 && (f100 >= 11 && f100 <= 19)) ? 'zero' + : (n10 == 1 && n100 != 11 || v == 2 && f10 == 1 && f100 != 11 + || v != 2 && f10 == 1) ? 'one' + : 'other'; +}, + +ps: _cp[1], + +pt: function(n, ord) { + var s = String(n).split('.'), t0 = Number(s[0]) == n; + if (ord) return 'other'; + return ((t0 && n >= 0 && n <= 2) && n != 2) ? 'one' : 'other'; +}, + +"pt-PT": _cp[3], + +rm: _cp[1], + +ro: function(n, ord) { + var s = String(n).split('.'), v0 = !s[1], t0 = Number(s[0]) == n, + n100 = t0 && s[0].slice(-2); + if (ord) return (n == 1) ? 'one' : 'other'; + return (n == 1 && v0) ? 'one' + : (!v0 || n == 0 + || n != 1 && (n100 >= 1 && n100 <= 19)) ? 'few' + : 'other'; +}, + +rof: _cp[1], + +root: _cp[0], + +ru: function(n, ord) { + var s = String(n).split('.'), i = s[0], v0 = !s[1], i10 = i.slice(-1), + i100 = i.slice(-2); + if (ord) return 'other'; + return (v0 && i10 == 1 && i100 != 11) ? 'one' + : (v0 && (i10 >= 2 && i10 <= 4) && (i100 < 12 + || i100 > 14)) ? 'few' + : (v0 && i10 == 0 || v0 && (i10 >= 5 && i10 <= 9) + || v0 && (i100 >= 11 && i100 <= 14)) ? 'many' + : 'other'; +}, + +rwk: _cp[1], + +sah: _cp[0], + +saq: _cp[1], + +sdh: _cp[1], + +se: function(n, ord) { + if (ord) return 'other'; + return (n == 1) ? 'one' + : (n == 2) ? 'two' + : 'other'; +}, + +seh: _cp[1], + +ses: _cp[0], + +sg: _cp[0], + +sh: function(n, ord) { + var s = String(n).split('.'), i = s[0], f = s[1] || '', v0 = !s[1], + i10 = i.slice(-1), i100 = i.slice(-2), f10 = f.slice(-1), f100 = f.slice(-2); + if (ord) return 'other'; + return (v0 && i10 == 1 && i100 != 11 + || f10 == 1 && f100 != 11) ? 'one' + : (v0 && (i10 >= 2 && i10 <= 4) && (i100 < 12 || i100 > 14) + || (f10 >= 2 && f10 <= 4) && (f100 < 12 + || f100 > 14)) ? 'few' + : 'other'; +}, + +shi: function(n, ord) { + var s = String(n).split('.'), t0 = Number(s[0]) == n; + if (ord) return 'other'; + return (n >= 0 && n <= 1) ? 'one' + : ((t0 && n >= 2 && n <= 10)) ? 'few' + : 'other'; +}, + +si: function(n, ord) { + var s = String(n).split('.'), i = s[0], f = s[1] || ''; + if (ord) return 'other'; + return ((n == 0 || n == 1) + || i == 0 && f == 1) ? 'one' : 'other'; +}, + +sk: function(n, ord) { + var s = String(n).split('.'), i = s[0], v0 = !s[1]; + if (ord) return 'other'; + return (n == 1 && v0) ? 'one' + : ((i >= 2 && i <= 4) && v0) ? 'few' + : (!v0) ? 'many' + : 'other'; +}, + +sl: function(n, ord) { + var s = String(n).split('.'), i = s[0], v0 = !s[1], i100 = i.slice(-2); + if (ord) return 'other'; + return (v0 && i100 == 1) ? 'one' + : (v0 && i100 == 2) ? 'two' + : (v0 && (i100 == 3 || i100 == 4) + || !v0) ? 'few' + : 'other'; +}, + +sma: function(n, ord) { + if (ord) return 'other'; + return (n == 1) ? 'one' + : (n == 2) ? 'two' + : 'other'; +}, + +smi: function(n, ord) { + if (ord) return 'other'; + return (n == 1) ? 'one' + : (n == 2) ? 'two' + : 'other'; +}, + +smj: function(n, ord) { + if (ord) return 'other'; + return (n == 1) ? 'one' + : (n == 2) ? 'two' + : 'other'; +}, + +smn: function(n, ord) { + if (ord) return 'other'; + return (n == 1) ? 'one' + : (n == 2) ? 'two' + : 'other'; +}, + +sms: function(n, ord) { + if (ord) return 'other'; + return (n == 1) ? 'one' + : (n == 2) ? 'two' + : 'other'; +}, + +sn: _cp[1], + +so: _cp[1], + +sq: function(n, ord) { + var s = String(n).split('.'), t0 = Number(s[0]) == n, + n10 = t0 && s[0].slice(-1), n100 = t0 && s[0].slice(-2); + if (ord) return (n == 1) ? 'one' + : (n10 == 4 && n100 != 14) ? 'many' + : 'other'; + return (n == 1) ? 'one' : 'other'; +}, + +sr: function(n, ord) { + var s = String(n).split('.'), i = s[0], f = s[1] || '', v0 = !s[1], + i10 = i.slice(-1), i100 = i.slice(-2), f10 = f.slice(-1), f100 = f.slice(-2); + if (ord) return 'other'; + return (v0 && i10 == 1 && i100 != 11 + || f10 == 1 && f100 != 11) ? 'one' + : (v0 && (i10 >= 2 && i10 <= 4) && (i100 < 12 || i100 > 14) + || (f10 >= 2 && f10 <= 4) && (f100 < 12 + || f100 > 14)) ? 'few' + : 'other'; +}, + +ss: _cp[1], + +ssy: _cp[1], + +st: _cp[1], + +sv: function(n, ord) { + var s = String(n).split('.'), v0 = !s[1], t0 = Number(s[0]) == n, + n10 = t0 && s[0].slice(-1), n100 = t0 && s[0].slice(-2); + if (ord) return ((n10 == 1 + || n10 == 2) && n100 != 11 && n100 != 12) ? 'one' : 'other'; + return (n == 1 && v0) ? 'one' : 'other'; +}, + +sw: _cp[3], + +syr: _cp[1], + +ta: _cp[1], + +te: _cp[1], + +teo: _cp[1], + +th: _cp[0], + +ti: _cp[2], + +tig: _cp[1], + +tk: _cp[1], + +tl: function(n, ord) { + var s = String(n).split('.'), i = s[0], f = s[1] || '', v0 = !s[1], + i10 = i.slice(-1), f10 = f.slice(-1); + if (ord) return (n == 1) ? 'one' : 'other'; + return (v0 && (i == 1 || i == 2 || i == 3) + || v0 && i10 != 4 && i10 != 6 && i10 != 9 + || !v0 && f10 != 4 && f10 != 6 && f10 != 9) ? 'one' : 'other'; +}, + +tn: _cp[1], + +to: _cp[0], + +tr: _cp[1], + +ts: _cp[1], + +tzm: function(n, ord) { + var s = String(n).split('.'), t0 = Number(s[0]) == n; + if (ord) return 'other'; + return ((n == 0 || n == 1) + || (t0 && n >= 11 && n <= 99)) ? 'one' : 'other'; +}, + +ug: _cp[1], + +uk: function(n, ord) { + var s = String(n).split('.'), i = s[0], v0 = !s[1], t0 = Number(s[0]) == n, + n10 = t0 && s[0].slice(-1), n100 = t0 && s[0].slice(-2), i10 = i.slice(-1), + i100 = i.slice(-2); + if (ord) return (n10 == 3 && n100 != 13) ? 'few' : 'other'; + return (v0 && i10 == 1 && i100 != 11) ? 'one' + : (v0 && (i10 >= 2 && i10 <= 4) && (i100 < 12 + || i100 > 14)) ? 'few' + : (v0 && i10 == 0 || v0 && (i10 >= 5 && i10 <= 9) + || v0 && (i100 >= 11 && i100 <= 14)) ? 'many' + : 'other'; +}, + +ur: _cp[3], + +uz: _cp[1], + +ve: _cp[1], + +vi: function(n, ord) { + if (ord) return (n == 1) ? 'one' : 'other'; + return 'other'; +}, + +vo: _cp[1], + +vun: _cp[1], + +wa: _cp[2], + +wae: _cp[1], + +wo: _cp[0], + +xh: _cp[1], + +xog: _cp[1], + +yi: _cp[3], + +yo: _cp[0], + +zh: _cp[0], + +zu: function(n, ord) { + if (ord) return 'other'; + return (n >= 0 && n <= 1) ? 'one' : 'other'; +} +})); + +},{}],8:[function(require,module,exports){ +/* + * Generated by PEG.js 0.10.0. * - * @author Alex Sexton - @SlexAxton - * @version 0.1.7 - * @license WTFPL - * @contributor_license Dojo CLA -*/ -(function ( root ) { + * http://pegjs.org/ + */ - // Create the contructor function - function MessageFormat ( locale, pluralFunc ) { - var fallbackLocale; +"use strict"; - if ( locale && pluralFunc ) { - MessageFormat.locale[ locale ] = pluralFunc; - } +function peg$subclass(child, parent) { + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor(); +} - // Defaults - fallbackLocale = locale = locale || "en"; - pluralFunc = pluralFunc || MessageFormat.locale[ fallbackLocale = MessageFormat.Utils.getFallbackLocale( locale ) ]; +function peg$SyntaxError(message, expected, found, location) { + this.message = message; + this.expected = expected; + this.found = found; + this.location = location; + this.name = "SyntaxError"; - if ( ! pluralFunc ) { - throw new Error( "Plural Function not found for locale: " + locale ); - } + if (typeof Error.captureStackTrace === "function") { + Error.captureStackTrace(this, peg$SyntaxError); + } +} + +peg$subclass(peg$SyntaxError, Error); + +peg$SyntaxError.buildMessage = function(expected, found) { + var DESCRIBE_EXPECTATION_FNS = { + literal: function(expectation) { + return "\"" + literalEscape(expectation.text) + "\""; + }, + + "class": function(expectation) { + var escapedParts = "", + i; + + for (i = 0; i < expectation.parts.length; i++) { + escapedParts += expectation.parts[i] instanceof Array + ? classEscape(expectation.parts[i][0]) + "-" + classEscape(expectation.parts[i][1]) + : classEscape(expectation.parts[i]); + } + + return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]"; + }, + + any: function(expectation) { + return "any character"; + }, + + end: function(expectation) { + return "end of input"; + }, + + other: function(expectation) { + return expectation.description; + } + }; - // Own Properties - this.pluralFunc = pluralFunc; - this.locale = locale; - this.fallbackLocale = fallbackLocale; + function hex(ch) { + return ch.charCodeAt(0).toString(16).toUpperCase(); } - // Set up the locales object. Add in english by default - MessageFormat.locale = { - "en" : function ( n ) { - if ( n === 1 ) { - return "one"; + function literalEscape(s) { + return s + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\0/g, '\\0') + .replace(/\t/g, '\\t') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) + .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); }); + } + + function classEscape(s) { + return s + .replace(/\\/g, '\\\\') + .replace(/\]/g, '\\]') + .replace(/\^/g, '\\^') + .replace(/-/g, '\\-') + .replace(/\0/g, '\\0') + .replace(/\t/g, '\\t') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) + .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); }); + } + + function describeExpectation(expectation) { + return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation); + } + + function describeExpected(expected) { + var descriptions = new Array(expected.length), + i, j; + + for (i = 0; i < expected.length; i++) { + descriptions[i] = describeExpectation(expected[i]); + } + + descriptions.sort(); + + if (descriptions.length > 0) { + for (i = 1, j = 1; i < descriptions.length; i++) { + if (descriptions[i - 1] !== descriptions[i]) { + descriptions[j] = descriptions[i]; + j++; + } } - return "other"; + descriptions.length = j; } - }; - // Build out our basic SafeString type - // more or less stolen from Handlebars by @wycats - MessageFormat.SafeString = function( string ) { - this.string = string; - }; + switch (descriptions.length) { + case 1: + return descriptions[0]; - MessageFormat.SafeString.prototype.toString = function () { - return this.string.toString(); - }; + case 2: + return descriptions[0] + " or " + descriptions[1]; - MessageFormat.Utils = { - numSub : function ( string, key, depth ) { - // make sure that it's not an escaped octothorpe - return string.replace( /^#|[^\\]#/g, function (m) { - var prefix = m && m.length === 2 ? m.charAt(0) : ''; - return prefix + '" + (function(){ var x = ' + - key+';\nif( isNaN(x) ){\nthrow new Error("MessageFormat: `"+lastkey_'+depth+'+"` isnt a number.");\n}\nreturn x;\n})() + "'; - }); - }, - escapeExpression : function (string) { - var escape = { - "\n": "\\n", - "\"": '\\"' - }, - badChars = /[\n"]/g, - possible = /[\n"]/, - escapeChar = function(chr) { - return escape[chr] || "&"; + default: + return descriptions.slice(0, -1).join(", ") + + ", or " + + descriptions[descriptions.length - 1]; + } + } + + function describeFound(found) { + return found ? "\"" + literalEscape(found) + "\"" : "end of input"; + } + + return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found."; +}; + +function peg$parse(input, options) { + options = options !== void 0 ? options : {}; + + var peg$FAILED = {}, + + peg$startRuleFunctions = { start: peg$parsestart }, + peg$startRuleFunction = peg$parsestart, + + peg$c0 = "#", + peg$c1 = peg$literalExpectation("#", false), + peg$c2 = function() { return { type: 'octothorpe' }; }, + peg$c3 = function(str) { return str.join(''); }, + peg$c4 = "{", + peg$c5 = peg$literalExpectation("{", false), + peg$c6 = "}", + peg$c7 = peg$literalExpectation("}", false), + peg$c8 = function(arg) { + return { + type: 'argument', + arg: arg }; + }, + peg$c9 = ",", + peg$c10 = peg$literalExpectation(",", false), + peg$c11 = "select", + peg$c12 = peg$literalExpectation("select", false), + peg$c13 = function(arg, cases) { + return { + type: 'select', + arg: arg, + cases: cases + }; + }, + peg$c14 = "plural", + peg$c15 = peg$literalExpectation("plural", false), + peg$c16 = "selectordinal", + peg$c17 = peg$literalExpectation("selectordinal", false), + peg$c18 = function(arg, type, offset, cases) { + var ls = ((type === 'selectordinal') ? options.ordinal : options.cardinal) + || ['zero', 'one', 'two', 'few', 'many', 'other']; + if (ls && ls.length) cases.forEach(function(c) { + if (isNaN(c.key) && ls.indexOf(c.key) < 0) throw new Error( + 'Invalid key `' + c.key + '` for argument `' + arg + '`.' + + ' Valid ' + type + ' keys for this locale are `' + ls.join('`, `') + + '`, and explicit keys like `=0`.'); + }); + return { + type: type, + arg: arg, + offset: offset || 0, + cases: cases + }; + }, + peg$c19 = function(arg, key, params) { + return { + type: 'function', + arg: arg, + key: key, + params: params + }; + }, + peg$c20 = /^[0-9a-zA-Z$_]/, + peg$c21 = peg$classExpectation([["0", "9"], ["a", "z"], ["A", "Z"], "$", "_"], false, false), + peg$c22 = /^[^ \t\n\r,.+={}]/, + peg$c23 = peg$classExpectation([" ", "\t", "\n", "\r", ",", ".", "+", "=", "{", "}"], true, false), + peg$c24 = function(key, tokens) { return { key: key, tokens: tokens }; }, + peg$c25 = function(tokens) { return tokens; }, + peg$c26 = "offset", + peg$c27 = peg$literalExpectation("offset", false), + peg$c28 = ":", + peg$c29 = peg$literalExpectation(":", false), + peg$c30 = function(d) { return d; }, + peg$c31 = "=", + peg$c32 = peg$literalExpectation("=", false), + peg$c33 = function(p) { return p; }, + peg$c34 = /^[^{}#\\\0-\x08\x0E-\x1F\x7F]/, + peg$c35 = peg$classExpectation(["{", "}", "#", "\\", ["\0", "\b"], ["\x0E", "\x1F"], "\x7F"], true, false), + peg$c36 = "\\\\", + peg$c37 = peg$literalExpectation("\\\\", false), + peg$c38 = function() { return '\\'; }, + peg$c39 = "\\#", + peg$c40 = peg$literalExpectation("\\#", false), + peg$c41 = function() { return '#'; }, + peg$c42 = "\\{", + peg$c43 = peg$literalExpectation("\\{", false), + peg$c44 = function() { return '\u007B'; }, + peg$c45 = "\\}", + peg$c46 = peg$literalExpectation("\\}", false), + peg$c47 = function() { return '\u007D'; }, + peg$c48 = "\\u", + peg$c49 = peg$literalExpectation("\\u", false), + peg$c50 = function(h1, h2, h3, h4) { + return String.fromCharCode(parseInt('0x' + h1 + h2 + h3 + h4)); + }, + peg$c51 = /^[0-9]/, + peg$c52 = peg$classExpectation([["0", "9"]], false, false), + peg$c53 = /^[0-9a-fA-F]/, + peg$c54 = peg$classExpectation([["0", "9"], ["a", "f"], ["A", "F"]], false, false), + peg$c55 = /^[ \t\n\r]/, + peg$c56 = peg$classExpectation([" ", "\t", "\n", "\r"], false, false), - // Don't escape SafeStrings, since they're already safe - if ( string instanceof MessageFormat.SafeString ) { - return string.toString(); - } - else if ( string === null || string === false ) { - return ""; - } + peg$currPos = 0, + peg$savedPos = 0, + peg$posDetailsCache = [{ line: 1, column: 1 }], + peg$maxFailPos = 0, + peg$maxFailExpected = [], + peg$silentFails = 0, + + peg$result; + + if ("startRule" in options) { + if (!(options.startRule in peg$startRuleFunctions)) { + throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); + } + + peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; + } + + function text() { + return input.substring(peg$savedPos, peg$currPos); + } + + function location() { + return peg$computeLocation(peg$savedPos, peg$currPos); + } + + function expected(description, location) { + location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos) + + throw peg$buildStructuredError( + [peg$otherExpectation(description)], + input.substring(peg$savedPos, peg$currPos), + location + ); + } + + function error(message, location) { + location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos) + + throw peg$buildSimpleError(message, location); + } + + function peg$literalExpectation(text, ignoreCase) { + return { type: "literal", text: text, ignoreCase: ignoreCase }; + } + + function peg$classExpectation(parts, inverted, ignoreCase) { + return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase }; + } + + function peg$anyExpectation() { + return { type: "any" }; + } + + function peg$endExpectation() { + return { type: "end" }; + } + + function peg$otherExpectation(description) { + return { type: "other", description: description }; + } + + function peg$computePosDetails(pos) { + var details = peg$posDetailsCache[pos], p; - if ( ! possible.test( string ) ) { - return string; + if (details) { + return details; + } else { + p = pos - 1; + while (!peg$posDetailsCache[p]) { + p--; } - return string.replace( badChars, escapeChar ); - }, - getFallbackLocale: function( locale ) { - var tagSeparator = locale.indexOf("-") >= 0 ? "-" : "_"; - - // Lets just be friends, fallback through the language tags - while ( ! MessageFormat.locale.hasOwnProperty( locale ) ) { - locale = locale.substring(0, locale.lastIndexOf( tagSeparator )); - if (locale.length === 0) { - return null; + + details = peg$posDetailsCache[p]; + details = { + line: details.line, + column: details.column + }; + + while (p < pos) { + if (input.charCodeAt(p) === 10) { + details.line++; + details.column = 1; + } else { + details.column++; } + + p++; } - return locale; + peg$posDetailsCache[pos] = details; + return details; } - }; + } - // This is generated and pulled in for browsers. - var mparser = (function(){ - /* - * Generated by PEG.js 0.7.0. - * - * http://pegjs.majda.cz/ - */ - - function quote(s) { - /* - * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a - * string literal except for the closing quote character, backslash, - * carriage return, line separator, paragraph separator, and line feed. - * Any character may appear in the form of an escape sequence. - * - * For portability, we also escape escape all control and non-ASCII - * characters. Note that "\0" and "\v" escape sequences are not used - * because JSHint does not like the first and IE the second. - */ - return '"' + s - .replace(/\\/g, '\\\\') // backslash - .replace(/"/g, '\\"') // closing quote character - .replace(/\x08/g, '\\b') // backspace - .replace(/\t/g, '\\t') // horizontal tab - .replace(/\n/g, '\\n') // line feed - .replace(/\f/g, '\\f') // form feed - .replace(/\r/g, '\\r') // carriage return - .replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, escape) - + '"'; - } - - var result = { - /* - * Parses the input with a generated parser. If the parsing is successfull, - * returns a value explicitly or implicitly specified by the grammar from - * which the parser was generated (see |PEG.buildParser|). If the parsing is - * unsuccessful, throws |PEG.parser.SyntaxError| describing the error. - */ - parse: function(input, startRule) { - var parseFunctions = { - "start": parse_start, - "messageFormatPattern": parse_messageFormatPattern, - "messageFormatPatternRight": parse_messageFormatPatternRight, - "messageFormatElement": parse_messageFormatElement, - "elementFormat": parse_elementFormat, - "pluralStyle": parse_pluralStyle, - "selectStyle": parse_selectStyle, - "pluralFormatPattern": parse_pluralFormatPattern, - "offsetPattern": parse_offsetPattern, - "selectFormatPattern": parse_selectFormatPattern, - "pluralForms": parse_pluralForms, - "stringKey": parse_stringKey, - "string": parse_string, - "id": parse_id, - "chars": parse_chars, - "char": parse_char, - "digits": parse_digits, - "hexDigit": parse_hexDigit, - "_": parse__, - "whitespace": parse_whitespace - }; - - if (startRule !== undefined) { - if (parseFunctions[startRule] === undefined) { - throw new Error("Invalid rule name: " + quote(startRule) + "."); - } - } else { - startRule = "start"; - } - - var pos = 0; - var reportFailures = 0; - var rightmostFailuresPos = 0; - var rightmostFailuresExpected = []; - - function padLeft(input, padding, length) { - var result = input; - - var padLength = length - input.length; - for (var i = 0; i < padLength; i++) { - result = padding + result; - } - - return result; - } - - function escape(ch) { - var charCode = ch.char <TRUNCATED>
