Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

messageformat

Package Overview
Dependencies
Maintainers
1
Versions
52
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

messageformat - npm Package Compare versions

Comparing version 0.2.1 to 0.3.0-0

example/fr/true

81

bin/messageformat.js
#!/usr/bin/env node
/**
* Copyright 2014
* Copyright 2012-2014 Alex Sexton, Eemeli Aro, and Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Licensed under the MIT License
*/

@@ -99,3 +89,3 @@

}
o.namespace = o.namespace.replace(/^window\./, '')
o.namespace = o.module ? 'module.exports' : o.namespace.replace(/^window\./, '')
return o;

@@ -106,3 +96,2 @@ })(),

function write(options, data) {
data = data.join('\n');
if (options.stdout) { _log(''); return console.log(data); }

@@ -115,24 +104,19 @@ fs.writeFile( options.output, data, 'utf8', function(err) {

function parseFileSync(options, mf, file) {
var path = Path.join(options.inputdir, file),
lc0 = mf.lc,
function parseFileSync(dir, file) {
var path = Path.join(dir, file),
file_parts = file.split(/[.\/]+/),
r = '';
r = { namespace: null, locale: null, data: null };
if (!fs.statSync(path).isFile()) {
_log('Skipping ' + file);
return '';
return null;
}
r.namespace = file.replace(/\.[^.]*$/, '').replace(/\\/g, '/');
for (var i = file_parts.length - 1; i >= 0; --i) {
if (file_parts[i] in MessageFormat.locale) { mf.lc = file_parts[i]; break; }
if (file_parts[i] in MessageFormat.plurals) { r.locale = file_parts[i]; break; }
}
try {
var text = fs.readFileSync(path, 'utf8'),
nm = file.replace(/\.[^.]*$/, '').replace(/\\/g, '/'),
gn = mf.globalName + '["' + nm + '"]';
_log('Building ' + gn + ' from `' + file + '` with locale "' + mf.lc + '"');
r = gn + '=' + mf.precompileObject(JSON.parse(text));
_log('Building ' + JSON.stringify(r.namespace) + ' from `' + file + '` with ' + (r.locale ? 'locale ' + JSON.stringify(r.locale) : 'default locale'));
r.data = JSON.parse(fs.readFileSync(path, 'utf8'));
} catch (ex) {
console.error('--->\tParse error in ' + path + ': ' + ex.message);
} finally {
mf.lc = lc0;
console.error('--->\tRead error in ' + path + ': ' + ex.message);
}

@@ -144,5 +128,10 @@ return r;

var lc = options.locale.trim().split(/[ ,]+/),
mf = new MessageFormat(lc[0], false, options.namespace),
compiledMessageFormat = [];
for (var i = 1; i < lc.length; ++i) MessageFormat.loadLocale(lc[i]);
mf = new MessageFormat(lc[0]),
messages = {},
compileOpt = { global: options.namespace, locale: {} };
for (var i = 1; i < lc.length; ++i) {
var pf = MessageFormat.getPluralFunc([lc[i]]);
if (!pf) throw 'Plural function for locale `' + lc[i] + '` could not be loaded';
mf.runtime.pluralFuncs[lc[i]] = pf;
}
_log('Input dir: ' + options.inputdir);

@@ -153,12 +142,14 @@ _log('Included locales: ' + lc.join(', '));

function(file, cb) {
var pf = parseFileSync(options, mf, file);
if (pf) compiledMessageFormat.push(pf);
var r = parseFileSync(options.inputdir, file);
if (r && r.data) {
messages[r.namespace] = r.data;
if (r.locale) compileOpt.locale[r.namespace] = r.locale;
}
cb();
},
function() {
if (options.module) {
return buildForCommonJSModule(mf, compiledMessageFormat, callback, options);
} else {
return buildForWindowGlobal(mf, compiledMessageFormat, callback, options);
}
var fn_str = mf.compile(messages, compileOpt).toString();
fn_str = fn_str.replace(/^\s*function\b[^{]*{\s*/, '').replace(/\s*}\s*$/, '');
var data = options.module ? fn_str : '(function(G) {\n' + fn_str + '\n})(this);';
return callback(options, data.trim() + '\n');
}

@@ -169,16 +160,2 @@ );

function buildForCommonJSModule(mf, compiledMessageFormat, callback, options) {
var data = ['var ' + mf.globalName + '=' + mf.functions() + ';']
.concat(compiledMessageFormat)
.concat('module.exports = ' + mf.globalName + ';\n');
return callback(options, data);
}
function buildForWindowGlobal(mf, compiledMessageFormat, callback, options) {
var data = ['(function(G){G[\'' + mf.globalName + '\']=' + mf.functions()]
.concat(compiledMessageFormat)
.concat('})(this);\n');
return callback(options, data);
}
build(options, write);

@@ -185,0 +162,0 @@

@@ -1,13 +0,40 @@

(function(G){G['i18n']={lc:{"en":function(n){return n===1?"one":"other"}},
c:function(d,k){if(!d)throw new Error("MessageFormat: Data required for '"+k+"'.")},
n:function(d,k,o){if(isNaN(d[k]))throw new Error("MessageFormat: '"+k+"' isn't a number.");return d[k]-(o||0)},
v:function(d,k){i18n.c(d,k);return d[k]},
p:function(d,k,o,l,p){i18n.c(d,k);return d[k] in p?p[d[k]]:(k=i18n.lc[l](d[k]-o),k in p?p[k]:p.other)},
s:function(d,k,p){i18n.c(d,k);return d[k] in p?p[d[k]]:p.other}}
i18n["colors"] = {
"red":function(d){return "red"},
"blue":function(d){return "blue"},
"green":function(d){return "green"}}
i18n["sub/folder/plural"] = {
"test":function(d){return "Your "+i18n.p(d,"NUM",0,"en",{"one":"message","other":"messages"})+" go here."}}
})(this);
(function(G) {
var number = function (value, offset) {
if (isNaN(value)) throw new Error("'" + value + "' isn't a number.");
return value - (offset || 0);
};
var plural = function (value, offset, lcfunc, data, isOrdinal) {
if (value in data) return data[value];
if (offset) value -= offset;
var key = lcfunc(value, isOrdinal);
if (key in data) return data[key];
return data.other;
};
var select = function (value, data) {
if (value in data) return data[value];
return data.other
};
var pluralFuncs = {
en: function(n,ord) {
var s = String(n).split('.'), v0 = !s[1], t0 = Number(s[0]) == n,
n10 = t0 && s[0].substr(-1), n100 = t0 && s[0].substr(-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';
}
};
var fmt = {};
G.i18n = {
colors: {
red: function(d) { return "red"; },
blue: function(d) { return "blue"; },
green: function(d) { return "green"; }
},
"sub/folder/plural": {
test: function(d) { return "Your " + plural(d.NUM, 0, pluralFuncs.en, { one: "message goes", other: "messages go" }) + " here."; }
}
}
})(this);
{
"test": "Your {NUM, plural, one{message} other{messages}} go here."
"test": "Your {NUM, plural, one{message goes} other{messages go}} here."
}

@@ -1,13 +0,35 @@

(function(G){G['i18n']={lc:{"fr":function(n){return n===0||n==1?"one":"other"}},
c:function(d,k){if(!d)throw new Error("MessageFormat: Data required for '"+k+"'.")},
n:function(d,k,o){if(isNaN(d[k]))throw new Error("MessageFormat: '"+k+"' isn't a number.");return d[k]-(o||0)},
v:function(d,k){i18n.c(d,k);return d[k]},
p:function(d,k,o,l,p){i18n.c(d,k);return d[k] in p?p[d[k]]:(k=i18n.lc[l](d[k]-o),k in p?p[k]:p.other)},
s:function(d,k,p){i18n.c(d,k);return d[k] in p?p[d[k]]:p.other}}
i18n["colors"] = {
"red":function(d){return "rouge"},
"blue":function(d){return "bleu"},
"green":function(d){return "vert"}}
i18n["sub/folder/plural"] = {
"test":function(d){return i18n.p(d,"NUM",0,"fr",{"one":"Votre message se trouve","other":"Vos messages se trouvent"})+" ici."}}
})(this);
(function(G) {
var number = function (value, offset) {
if (isNaN(value)) throw new Error("'" + value + "' isn't a number.");
return value - (offset || 0);
};
var plural = function (value, offset, lcfunc, data, isOrdinal) {
if (value in data) return data[value];
if (offset) value -= offset;
var key = lcfunc(value, isOrdinal);
if (key in data) return data[key];
return data.other;
};
var select = function (value, data) {
if (value in data) return data[value];
return data.other
};
var pluralFuncs = {
fr: function(n,ord) {
if (ord) return (n == 1) ? 'one' : 'other';
return (n >= 0 && n < 2) ? 'one' : 'other';
}
};
var fmt = {};
G.i18n = {
colors: {
red: function(d) { return "rouge"; },
blue: function(d) { return "bleu"; },
green: function(d) { return "vert"; }
},
"sub/folder/plural": {
test: function(d) { return plural(d.NUM, 0, pluralFuncs.fr, { one: "Votre message se trouve", other: "Vos messages se trouvent" }) + " ici."; }
}
}
})(this);
/**
* messageformat.js
*
* ICU PluralFormat + SelectFormat for JavaScript
*
* Copyright 2014
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @file messageformat.js - ICU PluralFormat + SelectFormat for JavaScript
* @author Alex Sexton - @SlexAxton
* @version 0.1.7
* @contributor_license Dojo CLA
* @version 0.3.0-0
* @copyright 2012-2015 Alex Sexton, Eemeli Aro, and Contributors
* @license To use or fork, MIT. To contribute back, Dojo CLA
*/
(function ( root ) {
function MessageFormat ( locale, pluralFunc, globalName ) {
var lc = locale || 'en', lcFile;
if ( pluralFunc ) {
MessageFormat.locale[lc] = pluralFunc;
/**
* Create a new message formatter
*
* @class
* @global
* @param {string|string[]} [locale="en"] - The locale to use, with fallbacks
* @param {function} [pluralFunc] - Optional custom pluralization function
* @param {function[]} [formatters] - Optional custom formatting functions
*/
function MessageFormat(locale, pluralFunc, formatters) {
if (!locale) {
this.lc = ['en'];
} else if (typeof locale == 'string') {
this.lc = [];
for (var l = locale; l; l = l.replace(/[-_]?[^-_]*$/, '')) this.lc.push(l);
} else {
while ( lc && ! MessageFormat.locale.hasOwnProperty( lc ) ) {
lc = lc.replace(/[-_]?[^-_]*$/, '');
}
if ( ! lc ) {
lc = locale.replace(/[-_].*$/, '');
MessageFormat.loadLocale(lc);
}
this.lc = locale;
}
this.lc = lc; // used in 'elementFormat'
this.globalName = globalName || 'i18n';
if (!pluralFunc) {
pluralFunc = MessageFormat.getPluralFunc(this.lc);
if (!pluralFunc) throw 'Plural function for locale `' + this.lc.join(',') + '` could not be loaded';
}
this.runtime.pluralFuncs = {};
this.runtime.pluralFuncs[this.lc[0]] = pluralFunc;
this.runtime.fmt = {};
if (formatters) for (var f in formatters) {
this.runtime.fmt[f] = formatters[f];
}
}
if ( !('locale' in MessageFormat) ) MessageFormat.locale = {};
/**
* Publicly-accessible cache of pluralization functions, this is normally
* filled by the internal `getPluralFunc()` function, but may be set
* externally if e.g. the external dependency {@link
* http://github.com/eemeli/make-plural.js make-plural} is not available.
*
* @memberof MessageFormat
* @type Object.<string,function>
* @example
* > var MessageFormat = require('messageformat');
* > MessageFormat.plurals.en = function(n) { // cardinal plurals only
* return (n == 1 && !String(n).split('.')[1]) ? 'one' : 'other';
* };
* > var mf = new MessageFormat('en');
* > var mfunc = mf.compile('You have {N, plural, one{1 item} other{# items}.');
* > mfunc({N:'1.0'})
* "You have 1.0 items."
*/
MessageFormat.plurals = {};
MessageFormat.loadLocale = function ( lc ) {
try {
var lcFile = require('path').join(__dirname, 'locale', lc + '.js'),
lcStr = ('' + require('fs').readFileSync(lcFile)).match(/{[^]*}/);
if (!lcStr) throw "no function found in file '" + lcFile + "'";
MessageFormat.locale[lc] = 'function(n)' + lcStr;
} catch (ex) {
if ( lc == 'en' ) {
MessageFormat.locale[lc] = 'function(n){return n===1?"one":"other"}';
} else {
ex.message = 'Locale ' + lc + ' could not be loaded: ' + ex.message;
throw ex;
/**
* Look up the plural formatting function for a given locale code.
*
* If the {@link http://github.com/eemeli/make-plural.js make-plural module}
* is not available, the {@link MessageFormat.plurals} object will need to be
* pre-populated for this to work.
*
* @private
* @memberof MessageFormat
* @requires module:eemeli/make-plural.js
* @param {string[]} locale - A preferentially ordered array of locale codes
* @returns {function} The first match found for the given locale(s)
*/
MessageFormat.getPluralFunc = function(locale) {
var MakePlural = (typeof require != 'undefined') && require('make-plural') || root.MakePlural || function() { return false; };
for (var i = 0; i < locale.length; ++i) {
var lc = locale[i];
if (lc in MessageFormat.plurals) {
return MessageFormat.plurals[lc];
}
var fn = MakePlural(lc, {ordinals:1, quiet:1});
if (fn) {
MessageFormat.plurals[lc] = fn;
return fn;
}
}
};
return null;
}
MessageFormat.prototype.functions = function () {
var l = [];
for ( var lc in MessageFormat.locale ) {
if ( MessageFormat.locale.hasOwnProperty(lc) ) {
l.push(JSON.stringify(lc) + ':' + MessageFormat.locale[lc].toString().trim());
/**
* 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.withIntlSupport} needs to be true for these
* functions to be available for inclusion in the output.
*
* @see MessageFormat#setIntlSupport
*
* @namespace
* @memberof MessageFormat
* @property {function} number - Represent a number as an integer, percent or currency value
* @property {function} date - Represent a date as a full/long/default/short string
* @property {function} time - Represent a time as a full/long/default/short string
* @example
* > var MessageFormat = require('messageformat');
* > var mf = (new MessageFormat('en')).setIntlSupport(true);
* > mf.currency = 'EUR';
* > var mfunc = mf.compile("The total is {V,number,currency}.");
* > mfunc({V:5.5})
* "The total is €5.50."
* @example
* > var MessageFormat = require('messageformat');
* > var mf = new MessageFormat('en', null, {number: MessageFormat.number});
* > mf.currency = 'EUR';
* > var mfunc = mf.compile("The total is {V,number,currency}.");
* > mfunc({V:5.5})
* "The total is €5.50."
*/
MessageFormat.formatters = {
number: function(self) {
return new Function("v,lc,p",
"return 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)"
);
},
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)
},
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.minute;
}
return (new Date(v)).toLocaleTimeString(lc, o)
}
return '{lc:{' + l.join(',') + '},\n'
+ 'c:function(d,k){if(!d)throw new Error("MessageFormat: Data required for \'"+k+"\'.")},\n'
+ 'n:function(d,k,o){if(isNaN(d[k]))throw new Error("MessageFormat: \'"+k+"\' isn\'t a number.");return d[k]-(o||0)},\n'
+ 'v:function(d,k){' + this.globalName + '.c(d,k);return d[k]},\n'
+ 'p:function(d,k,o,l,p){' + this.globalName + '.c(d,k);return d[k] in p?p[d[k]]:(k=' + this.globalName + '.lc[l](d[k]-o),k in p?p[k]:p.other)},\n'
+ 's:function(d,k,p){' + this.globalName + '.c(d,k);return d[k] in p?p[d[k]]:p.other}}';
};
// This is generated and pulled in for browsers.
var mparser = (function() {
/*
* Generated by PEG.js 0.8.0.
/**
* 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 {Object} The MessageFormat instance, to allow for chaining
* @example
* > var Intl = require('intl');
* > var MessageFormat = require('messageformat');
* > var mf = (new MessageFormat('en')).setIntlSupport(true);
* > mf.currency = 'EUR';
* > mf.compile("The total is {V,number,currency}.")({V:5.5});
* "The total is €5.50."
*/
MessageFormat.prototype.setIntlSupport = function(enable) {
this.withIntlSupport = !!enable || (typeof enable == 'undefined');
return this;
};
/**
* 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()}.
*
* @namespace
* @memberof MessageFormat
*/
MessageFormat.prototype.runtime = {
/**
* Utility function for `#` in plural rules
*
* http://pegjs.majda.cz/
* @param {number} value - The value to operate on
* @param {number} [offset=0] - An optional offset, set by the surrounding context
*/
function peg$subclass(child, parent) {
function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype;
child.prototype = new ctor();
number: function(value, offset) {
if (isNaN(value)) throw new Error("'" + value + "' isn't a number.");
return value - (offset || 0);
},
/**
* 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
*/
plural: function(value, offset, lcfunc, data, isOrdinal) {
if (value in data) 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
*/
select: function(value, data) {
if (value in data) return data[value];
return data.other
},
/** Pluralization functions
* @instance
* @type Object.<string,function> */
pluralFuncs: {},
/** Custom formatting functions called by `{var, fn[, args]*}` syntax
* @instance
* @see MessageFormat.formatters
* @type Object.<string,function> */
fmt: {},
/** Custom stringifier to clean up browser inconsistencies */
toString: function () {
var _stringify = function(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 (i != 'toString') {
if (level == 0) s.push('var ' + i + ' = ' + _stringify(o[i], level + 1) + ';\n');
else s.push(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}';
};
return _stringify(this, 0);
}
function SyntaxError(message, expected, found, offset, line, column) {
this.message = message;
this.expected = expected;
this.found = found;
this.offset = offset;
this.line = line;
this.column = column;
this.name = "SyntaxError";
}
peg$subclass(SyntaxError, Error);
function parse(input) {
var options = arguments.length > 1 ? arguments[1] : {},
peg$FAILED = {},
peg$startRuleFunctions = { start: peg$parsestart },
peg$startRuleFunction = peg$parsestart,
peg$c0 = function(messageFormatPattern) { return { type: "program", program: messageFormatPattern }; },
peg$c1 = peg$FAILED,
peg$c2 = [],
peg$c3 = function(s1, inner) {
var st = [];
if ( s1 && s1.val ) {
st.push( s1 );
}
for( var i in inner ){
if ( inner.hasOwnProperty( i ) ) {
st.push( inner[ i ] );
}
}
return { type: 'messageFormatPattern', statements: st };
},
peg$c4 = "{",
peg$c5 = { type: "literal", value: "{", description: "\"{\"" },
peg$c6 = "}",
peg$c7 = { type: "literal", value: "}", description: "\"}\"" },
peg$c8 = function(mfe, s1) {
var res = [];
if ( mfe ) {
res.push(mfe);
}
if ( s1 && s1.val ) {
res.push( s1 );
}
return { type: "messageFormatPatternRight", statements : res };
},
peg$c9 = null,
peg$c10 = ",",
peg$c11 = { type: "literal", value: ",", description: "\",\"" },
peg$c12 = function(argIdx, efmt) {
var res = {
type: "messageFormatElement",
argumentIndex: argIdx
};
if ( efmt && efmt.length ) {
res.elementFormat = efmt[1];
}
else {
res.output = true;
}
return res;
},
peg$c13 = "plural",
peg$c14 = { type: "literal", value: "plural", description: "\"plural\"" },
peg$c15 = function(t, s) {
return {
type : "elementFormat",
key : t,
val : s.val
};
},
peg$c16 = "select",
peg$c17 = { type: "literal", value: "select", description: "\"select\"" },
peg$c18 = function(pfp) {
return { type: "pluralStyle", val: pfp };
},
peg$c19 = function(sfp) {
return { type: "selectStyle", val: sfp };
},
peg$c20 = function(op, pf) {
var res = {
type: "pluralFormatPattern",
pluralForms: pf
};
if ( op ) {
res.offset = op;
}
else {
res.offset = 0;
}
return res;
},
peg$c21 = "offset",
peg$c22 = { type: "literal", value: "offset", description: "\"offset\"" },
peg$c23 = ":",
peg$c24 = { type: "literal", value: ":", description: "\":\"" },
peg$c25 = function(d) {
return d;
},
peg$c26 = function(pf) {
return {
type: "selectFormatPattern",
pluralForms: pf
};
},
peg$c27 = function(k, mfp) {
return {
type: "pluralForms",
key: k,
val: mfp
};
},
peg$c28 = function(i) {
return i;
},
peg$c29 = "=",
peg$c30 = { type: "literal", value: "=", description: "\"=\"" },
peg$c31 = function(ws, s) {
var tmp = [];
for( var i = 0; i < s.length; ++i ) {
for( var j = 0; j < s[ i ].length; ++j ) {
tmp.push(s[i][j]);
}
}
return {
type: "string",
val: ws + tmp.join('')
};
},
peg$c32 = /^[0-9a-zA-Z$_]/,
peg$c33 = { type: "class", value: "[0-9a-zA-Z$_]", description: "[0-9a-zA-Z$_]" },
peg$c34 = /^[^ \t\n\r,.+={}]/,
peg$c35 = { type: "class", value: "[^ \\t\\n\\r,.+={}]", description: "[^ \\t\\n\\r,.+={}]" },
peg$c36 = function(s1, s2) {
return s1 + (s2 ? s2.join('') : '');
},
peg$c37 = function(chars) { return chars.join(''); },
peg$c38 = /^[^{}\\\0-\x1F \t\n\r]/,
peg$c39 = { type: "class", value: "[^{}\\\\\\0-\\x1F \\t\\n\\r]", description: "[^{}\\\\\\0-\\x1F \\t\\n\\r]" },
peg$c40 = function(x) {
return x;
},
peg$c41 = "\\#",
peg$c42 = { type: "literal", value: "\\#", description: "\"\\\\#\"" },
peg$c43 = function() {
return "\\#";
},
peg$c44 = "\\{",
peg$c45 = { type: "literal", value: "\\{", description: "\"\\\\{\"" },
peg$c46 = function() {
return "\u007B";
},
peg$c47 = "\\}",
peg$c48 = { type: "literal", value: "\\}", description: "\"\\\\}\"" },
peg$c49 = function() {
return "\u007D";
},
peg$c50 = "\\u",
peg$c51 = { type: "literal", value: "\\u", description: "\"\\\\u\"" },
peg$c52 = function(h1, h2, h3, h4) {
return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4));
},
peg$c53 = /^[0-9]/,
peg$c54 = { type: "class", value: "[0-9]", description: "[0-9]" },
peg$c55 = function(ds) {
return parseInt((ds.join('')), 10);
},
peg$c56 = /^[0-9a-fA-F]/,
peg$c57 = { type: "class", value: "[0-9a-fA-F]", description: "[0-9a-fA-F]" },
peg$c58 = { type: "other", description: "whitespace" },
peg$c59 = function(w) { return w.join(''); },
peg$c60 = /^[ \t\n\r]/,
peg$c61 = { type: "class", value: "[ \\t\\n\\r]", description: "[ \\t\\n\\r]" },
peg$currPos = 0,
peg$reportedPos = 0,
peg$cachedPos = 0,
peg$cachedPosDetails = { line: 1, column: 1, seenCR: false },
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];
};
/** Parse an input string to its AST
* @private */
MessageFormat._parse = function () {
// This is generated and pulled in for browsers.
var mparser = (function() {
/*
* Generated by PEG.js 0.8.0.
*
* http://pegjs.majda.cz/
*/
function peg$subclass(child, parent) {
function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype;
child.prototype = new ctor();
}
function text() {
return input.substring(peg$reportedPos, peg$currPos);
function SyntaxError(message, expected, found, offset, line, column) {
this.message = message;
this.expected = expected;
this.found = found;
this.offset = offset;
this.line = line;
this.column = column;
this.name = "SyntaxError";
}
function offset() {
return peg$reportedPos;
}
function line() {
return peg$computePosDetails(peg$reportedPos).line;
}
function column() {
return peg$computePosDetails(peg$reportedPos).column;
}
function expected(description) {
throw peg$buildException(
null,
[{ type: "other", description: description }],
peg$reportedPos
);
}
function error(message) {
throw peg$buildException(message, null, peg$reportedPos);
}
function peg$computePosDetails(pos) {
function advance(details, startPos, endPos) {
var p, ch;
for (p = startPos; p < endPos; p++) {
ch = input.charAt(p);
if (ch === "\n") {
if (!details.seenCR) { details.line++; }
details.column = 1;
details.seenCR = false;
} else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
details.line++;
details.column = 1;
details.seenCR = true;
} else {
details.column++;
details.seenCR = false;
}
peg$subclass(SyntaxError, Error);
function parse(input) {
var options = arguments.length > 1 ? arguments[1] : {},
peg$FAILED = {},
peg$startRuleFunctions = { start: peg$parsestart },
peg$startRuleFunction = peg$parsestart,
peg$c0 = peg$FAILED,
peg$c1 = [],
peg$c2 = function(s1, inner) {
var st = [];
if (s1 && s1.val) st.push(s1);
for (var i = 0; i < inner.length; i++) {
st.push(inner[i][0]);
if (inner[i][1].val !== "") st.push(inner[i][1]);
}
return { type: 'messageFormatPattern', statements: st };
},
peg$c3 = "{",
peg$c4 = { type: "literal", value: "{", description: "\"{\"" },
peg$c5 = null,
peg$c6 = ",",
peg$c7 = { type: "literal", value: ",", description: "\",\"" },
peg$c8 = "}",
peg$c9 = { type: "literal", value: "}", description: "\"}\"" },
peg$c10 = function(argIdx, efmt) {
var res = {
type: "messageFormatElement",
argumentIndex: argIdx
};
if (efmt && efmt.length) {
res.elementFormat = efmt[1];
} else {
res.output = true;
}
return res;
},
peg$c11 = "plural",
peg$c12 = { type: "literal", value: "plural", description: "\"plural\"" },
peg$c13 = function(t, s) {
return { type: "elementFormat", key: t, val: s };
},
peg$c14 = "selectordinal",
peg$c15 = { type: "literal", value: "selectordinal", description: "\"selectordinal\"" },
peg$c16 = "select",
peg$c17 = { type: "literal", value: "select", description: "\"select\"" },
peg$c18 = function(t, p) {
return { type: "elementFormat", key: t, val: p };
},
peg$c19 = function(op, pf) {
return { type: "pluralFormatPattern", pluralForms: pf, offset: op || 0 };
},
peg$c20 = "offset",
peg$c21 = { type: "literal", value: "offset", description: "\"offset\"" },
peg$c22 = ":",
peg$c23 = { type: "literal", value: ":", description: "\":\"" },
peg$c24 = function(d) { return d; },
peg$c25 = function(pf) { return { type: "selectFormatPattern", pluralForms: pf }; },
peg$c26 = function(k, mfp) {
return { type: "pluralForms", key: k, val: mfp };
},
peg$c27 = function(i) { return i; },
peg$c28 = "=",
peg$c29 = { type: "literal", value: "=", description: "\"=\"" },
peg$c30 = function(p) { return p; },
peg$c31 = function(s) { return { type: "string", val: s.join('') }; },
peg$c32 = { type: "other", description: "identifier" },
peg$c33 = /^[0-9a-zA-Z$_]/,
peg$c34 = { type: "class", value: "[0-9a-zA-Z$_]", description: "[0-9a-zA-Z$_]" },
peg$c35 = /^[^ \t\n\r,.+={}]/,
peg$c36 = { type: "class", value: "[^ \\t\\n\\r,.+={}]", description: "[^ \\t\\n\\r,.+={}]" },
peg$c37 = function(s) { return s; },
peg$c38 = function(chars) { return chars.join(''); },
peg$c39 = /^[^{}\\\0-\x1F \t\n\r]/,
peg$c40 = { type: "class", value: "[^{}\\\\\\0-\\x1F \\t\\n\\r]", description: "[^{}\\\\\\0-\\x1F \\t\\n\\r]" },
peg$c41 = function(x) { return x; },
peg$c42 = "\\#",
peg$c43 = { type: "literal", value: "\\#", description: "\"\\\\#\"" },
peg$c44 = function() { return "\\#"; },
peg$c45 = "\\{",
peg$c46 = { type: "literal", value: "\\{", description: "\"\\\\{\"" },
peg$c47 = function() { return "\u007B"; },
peg$c48 = "\\}",
peg$c49 = { type: "literal", value: "\\}", description: "\"\\\\}\"" },
peg$c50 = function() { return "\u007D"; },
peg$c51 = "\\u",
peg$c52 = { type: "literal", value: "\\u", description: "\"\\\\u\"" },
peg$c53 = function(h1, h2, h3, h4) {
return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4));
},
peg$c54 = /^[0-9]/,
peg$c55 = { type: "class", value: "[0-9]", description: "[0-9]" },
peg$c56 = function(ds) {
//the number might start with 0 but must not be interpreted as an octal number
//Hence, the base is passed to parseInt explicitely
return parseInt((ds.join('')), 10);
},
peg$c57 = /^[0-9a-fA-F]/,
peg$c58 = { type: "class", value: "[0-9a-fA-F]", description: "[0-9a-fA-F]" },
peg$c59 = { type: "other", description: "whitespace" },
peg$c60 = function(w) { return w.join(''); },
peg$c61 = /^[ \t\n\r]/,
peg$c62 = { type: "class", value: "[ \\t\\n\\r]", description: "[ \\t\\n\\r]" },
peg$currPos = 0,
peg$reportedPos = 0,
peg$cachedPos = 0,
peg$cachedPosDetails = { line: 1, column: 1, seenCR: false },
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];
}
if (peg$cachedPos !== pos) {
if (peg$cachedPos > pos) {
peg$cachedPos = 0;
peg$cachedPosDetails = { line: 1, column: 1, seenCR: false };
}
advance(peg$cachedPosDetails, peg$cachedPos, pos);
peg$cachedPos = pos;
function text() {
return input.substring(peg$reportedPos, peg$currPos);
}
return peg$cachedPosDetails;
}
function peg$fail(expected) {
if (peg$currPos < peg$maxFailPos) { return; }
if (peg$currPos > peg$maxFailPos) {
peg$maxFailPos = peg$currPos;
peg$maxFailExpected = [];
function offset() {
return peg$reportedPos;
}
peg$maxFailExpected.push(expected);
}
function peg$buildException(message, expected, pos) {
function cleanupExpected(expected) {
var i = 1;
expected.sort(function(a, b) {
if (a.description < b.description) {
return -1;
} else if (a.description > b.description) {
return 1;
} else {
return 0;
function line() {
return peg$computePosDetails(peg$reportedPos).line;
}
function column() {
return peg$computePosDetails(peg$reportedPos).column;
}
function expected(description) {
throw peg$buildException(
null,
[{ type: "other", description: description }],
peg$reportedPos
);
}
function error(message) {
throw peg$buildException(message, null, peg$reportedPos);
}
function peg$computePosDetails(pos) {
function advance(details, startPos, endPos) {
var p, ch;
for (p = startPos; p < endPos; p++) {
ch = input.charAt(p);
if (ch === "\n") {
if (!details.seenCR) { details.line++; }
details.column = 1;
details.seenCR = false;
} else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
details.line++;
details.column = 1;
details.seenCR = true;
} else {
details.column++;
details.seenCR = false;
}
}
});
while (i < expected.length) {
if (expected[i - 1] === expected[i]) {
expected.splice(i, 1);
} else {
i++;
}
if (peg$cachedPos !== pos) {
if (peg$cachedPos > pos) {
peg$cachedPos = 0;
peg$cachedPosDetails = { line: 1, column: 1, seenCR: false };
}
advance(peg$cachedPosDetails, peg$cachedPos, pos);
peg$cachedPos = pos;
}
return peg$cachedPosDetails;
}
function buildMessage(expected, found) {
function stringEscape(s) {
function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
return s
.replace(/\\/g, '\\\\')
.replace(/"/g, '\\"')
.replace(/\x08/g, '\\b')
.replace(/\t/g, '\\t')
.replace(/\n/g, '\\n')
.replace(/\f/g, '\\f')
.replace(/\r/g, '\\r')
.replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
.replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
.replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
.replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
function peg$fail(expected) {
if (peg$currPos < peg$maxFailPos) { return; }
if (peg$currPos > peg$maxFailPos) {
peg$maxFailPos = peg$currPos;
peg$maxFailExpected = [];
}
var expectedDescs = new Array(expected.length),
expectedDesc, foundDesc, i;
for (i = 0; i < expected.length; i++) {
expectedDescs[i] = expected[i].description;
}
expectedDesc = expected.length > 1
? expectedDescs.slice(0, -1).join(", ")
+ " or "
+ expectedDescs[expected.length - 1]
: expectedDescs[0];
foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";
return "Expected " + expectedDesc + " but " + foundDesc + " found.";
peg$maxFailExpected.push(expected);
}
var posDetails = peg$computePosDetails(pos),
found = pos < input.length ? input.charAt(pos) : null;
if (expected !== null) {
cleanupExpected(expected);
}
return new SyntaxError(
message !== null ? message : buildMessage(expected, found),
expected,
found,
pos,
posDetails.line,
posDetails.column
);
}
function peg$parsestart() {
var s0, s1;
s0 = peg$currPos;
s1 = peg$parsemessageFormatPattern();
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c0(s1);
}
s0 = s1;
return s0;
}
function peg$parsemessageFormatPattern() {
var s0, s1, s2, s3;
s0 = peg$currPos;
s1 = peg$parsestring();
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$parsemessageFormatPatternRight();
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$parsemessageFormatPatternRight();
function peg$buildException(message, expected, pos) {
function cleanupExpected(expected) {
var i = 1;
expected.sort(function(a, b) {
if (a.description < b.description) {
return -1;
} else if (a.description > b.description) {
return 1;
} else {
return 0;
}
});
while (i < expected.length) {
if (expected[i - 1] === expected[i]) {
expected.splice(i, 1);
} else {
i++;
}
}
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c3(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
function buildMessage(expected, found) {
function stringEscape(s) {
function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
return s
.replace(/\\/g, '\\\\')
.replace(/"/g, '\\"')
.replace(/\x08/g, '\\b')
.replace(/\t/g, '\\t')
.replace(/\n/g, '\\n')
.replace(/\f/g, '\\f')
.replace(/\r/g, '\\r')
.replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
.replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
.replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
.replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
}
var expectedDescs = new Array(expected.length),
expectedDesc, foundDesc, i;
for (i = 0; i < expected.length; i++) {
expectedDescs[i] = expected[i].description;
}
expectedDesc = expected.length > 1
? expectedDescs.slice(0, -1).join(", ")
+ " or "
+ expectedDescs[expected.length - 1]
: expectedDescs[0];
foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";
return "Expected " + expectedDesc + " but " + foundDesc + " found.";
}
} else {
peg$currPos = s0;
s0 = peg$c1;
var posDetails = peg$computePosDetails(pos),
found = pos < input.length ? input.charAt(pos) : null;
if (expected !== null) {
cleanupExpected(expected);
}
return new SyntaxError(
message !== null ? message : buildMessage(expected, found),
expected,
found,
pos,
posDetails.line,
posDetails.column
);
}
return s0;
}
function peg$parsemessageFormatPatternRight() {
var s0, s1, s2, s3, s4, s5, s6;
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 123) {
s1 = peg$c4;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c5); }
function peg$parsestart() {
var s0;
s0 = peg$parsemessageFormatPattern();
return s0;
}
if (s1 !== peg$FAILED) {
s2 = peg$parse_();
if (s2 !== peg$FAILED) {
s3 = peg$parsemessageFormatElement();
if (s3 !== peg$FAILED) {
s4 = peg$parse_();
function peg$parsemessageFormatPattern() {
var s0, s1, s2, s3, s4, s5;
s0 = peg$currPos;
s1 = peg$parsestring();
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$currPos;
s4 = peg$parsemessageFormatElement();
if (s4 !== peg$FAILED) {
s5 = peg$parsestring();
if (s5 !== peg$FAILED) {
s4 = [s4, s5];
s3 = s4;
} else {
peg$currPos = s3;
s3 = peg$c0;
}
} else {
peg$currPos = s3;
s3 = peg$c0;
}
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$currPos;
s4 = peg$parsemessageFormatElement();
if (s4 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 125) {
s5 = peg$c6;
peg$currPos++;
} else {
s5 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c7); }
}
s5 = peg$parsestring();
if (s5 !== peg$FAILED) {
s6 = peg$parsestring();
if (s6 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c8(s3, s6);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
s4 = [s4, s5];
s3 = s4;
} else {
peg$currPos = s0;
s0 = peg$c1;
peg$currPos = s3;
s3 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
peg$currPos = s3;
s3 = peg$c0;
}
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c2(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
return s0;
}
return s0;
}
function peg$parsemessageFormatElement() {
var s0, s1, s2, s3, s4;
s0 = peg$currPos;
s1 = peg$parseid();
if (s1 !== peg$FAILED) {
s2 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 44) {
s3 = peg$c10;
function peg$parsemessageFormatElement() {
var s0, s1, s2, s3, s4, s5, s6;
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 123) {
s1 = peg$c3;
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c11); }
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c4); }
}
if (s3 !== peg$FAILED) {
s4 = peg$parseelementFormat();
if (s4 !== peg$FAILED) {
s3 = [s3, s4];
s2 = s3;
} else {
peg$currPos = s2;
s2 = peg$c1;
}
} else {
peg$currPos = s2;
s2 = peg$c1;
}
if (s2 === peg$FAILED) {
s2 = peg$c9;
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c12(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
return s0;
}
function peg$parseelementFormat() {
var s0, s1, s2, s3, s4, s5, s6, s7;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
if (input.substr(peg$currPos, 6) === peg$c13) {
s2 = peg$c13;
peg$currPos += 6;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c14); }
}
if (s2 !== peg$FAILED) {
s3 = peg$parse_();
if (s3 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 44) {
s4 = peg$c10;
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c11); }
}
if (s4 !== peg$FAILED) {
s5 = peg$parse_();
if (s1 !== peg$FAILED) {
s2 = peg$parse_();
if (s2 !== peg$FAILED) {
s3 = peg$parseid();
if (s3 !== peg$FAILED) {
s4 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 44) {
s5 = peg$c6;
peg$currPos++;
} else {
s5 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c7); }
}
if (s5 !== peg$FAILED) {
s6 = peg$parsepluralStyle();
s6 = peg$parseelementFormat();
if (s6 !== peg$FAILED) {
s7 = peg$parse_();
if (s7 !== peg$FAILED) {
s5 = [s5, s6];
s4 = s5;
} else {
peg$currPos = s4;
s4 = peg$c0;
}
} else {
peg$currPos = s4;
s4 = peg$c0;
}
if (s4 === peg$FAILED) {
s4 = peg$c5;
}
if (s4 !== peg$FAILED) {
s5 = peg$parse_();
if (s5 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 125) {
s6 = peg$c8;
peg$currPos++;
} else {
s6 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c9); }
}
if (s6 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c15(s2, s6);
s1 = peg$c10(s3, s4);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
return s0;
}
if (s0 === peg$FAILED) {
function peg$parseelementFormat() {
var s0, s1, s2, s3, s4, s5, s6, s7;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
if (input.substr(peg$currPos, 6) === peg$c16) {
s2 = peg$c16;
if (input.substr(peg$currPos, 6) === peg$c11) {
s2 = peg$c11;
peg$currPos += 6;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c17); }
if (peg$silentFails === 0) { peg$fail(peg$c12); }
}

@@ -658,7 +725,7 @@ if (s2 !== peg$FAILED) {

if (input.charCodeAt(peg$currPos) === 44) {
s4 = peg$c10;
s4 = peg$c6;
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c11); }
if (peg$silentFails === 0) { peg$fail(peg$c7); }
}

@@ -668,3 +735,3 @@ if (s4 !== peg$FAILED) {

if (s5 !== peg$FAILED) {
s6 = peg$parseselectStyle();
s6 = peg$parsepluralFormatPattern();
if (s6 !== peg$FAILED) {

@@ -674,373 +741,491 @@ s7 = peg$parse_();

peg$reportedPos = s0;
s1 = peg$c15(s2, s6);
s1 = peg$c13(s2, s6);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
}
return s0;
}
function peg$parsepluralStyle() {
var s0, s1;
s0 = peg$currPos;
s1 = peg$parsepluralFormatPattern();
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c18(s1);
}
s0 = s1;
return s0;
}
function peg$parseselectStyle() {
var s0, s1;
s0 = peg$currPos;
s1 = peg$parseselectFormatPattern();
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c19(s1);
}
s0 = s1;
return s0;
}
function peg$parsepluralFormatPattern() {
var s0, s1, s2, s3;
s0 = peg$currPos;
s1 = peg$parseoffsetPattern();
if (s1 === peg$FAILED) {
s1 = peg$c9;
}
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$parsepluralForms();
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$parsepluralForms();
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c20(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}
return s0;
}
function peg$parseoffsetPattern() {
var s0, s1, s2, s3, s4, s5, s6, s7;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
if (input.substr(peg$currPos, 6) === peg$c21) {
s2 = peg$c21;
peg$currPos += 6;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c22); }
}
if (s2 !== peg$FAILED) {
s3 = peg$parse_();
if (s3 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 58) {
s4 = peg$c23;
peg$currPos++;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
if (input.substr(peg$currPos, 13) === peg$c14) {
s2 = peg$c14;
peg$currPos += 13;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c24); }
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c15); }
}
if (s4 !== peg$FAILED) {
s5 = peg$parse_();
if (s5 !== peg$FAILED) {
s6 = peg$parsedigits();
if (s6 !== peg$FAILED) {
s7 = peg$parse_();
if (s7 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c25(s6);
s0 = s1;
if (s2 !== peg$FAILED) {
s3 = peg$parse_();
if (s3 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 44) {
s4 = peg$c6;
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c7); }
}
if (s4 !== peg$FAILED) {
s5 = peg$parse_();
if (s5 !== peg$FAILED) {
s6 = peg$parseselectFormatPattern();
if (s6 !== peg$FAILED) {
s7 = peg$parse_();
if (s7 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c13(s2, s6);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
if (input.substr(peg$currPos, 6) === peg$c16) {
s2 = peg$c16;
peg$currPos += 6;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c17); }
}
if (s2 !== peg$FAILED) {
s3 = peg$parse_();
if (s3 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 44) {
s4 = peg$c6;
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c7); }
}
if (s4 !== peg$FAILED) {
s5 = peg$parse_();
if (s5 !== peg$FAILED) {
s6 = peg$parseselectFormatPattern();
if (s6 !== peg$FAILED) {
s7 = peg$parse_();
if (s7 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c13(s2, s6);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
s2 = peg$parseid();
if (s2 !== peg$FAILED) {
s3 = [];
s4 = peg$parseargStylePattern();
while (s4 !== peg$FAILED) {
s3.push(s4);
s4 = peg$parseargStylePattern();
}
if (s3 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c18(s2, s3);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
}
}
}
return s0;
}
function peg$parsepluralFormatPattern() {
var s0, s1, s2, s3;
s0 = peg$currPos;
s1 = peg$parseoffsetPattern();
if (s1 === peg$FAILED) {
s1 = peg$c5;
}
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$parsepluralForms();
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$parsepluralForms();
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c19(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
return s0;
}
return s0;
}
function peg$parseselectFormatPattern() {
var s0, s1, s2;
s0 = peg$currPos;
s1 = [];
s2 = peg$parsepluralForms();
while (s2 !== peg$FAILED) {
s1.push(s2);
s2 = peg$parsepluralForms();
}
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c26(s1);
}
s0 = s1;
return s0;
}
function peg$parsepluralForms() {
var s0, s1, s2, s3, s4, s5, s6, s7, s8;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
s2 = peg$parsestringKey();
if (s2 !== peg$FAILED) {
s3 = peg$parse_();
if (s3 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 123) {
s4 = peg$c4;
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c5); }
}
if (s4 !== peg$FAILED) {
s5 = peg$parse_();
if (s5 !== peg$FAILED) {
s6 = peg$parsemessageFormatPattern();
if (s6 !== peg$FAILED) {
s7 = peg$parse_();
if (s7 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 125) {
s8 = peg$c6;
peg$currPos++;
} else {
s8 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c7); }
}
if (s8 !== peg$FAILED) {
function peg$parseoffsetPattern() {
var s0, s1, s2, s3, s4, s5, s6, s7;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
if (input.substr(peg$currPos, 6) === peg$c20) {
s2 = peg$c20;
peg$currPos += 6;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c21); }
}
if (s2 !== peg$FAILED) {
s3 = peg$parse_();
if (s3 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 58) {
s4 = peg$c22;
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c23); }
}
if (s4 !== peg$FAILED) {
s5 = peg$parse_();
if (s5 !== peg$FAILED) {
s6 = peg$parsedigits();
if (s6 !== peg$FAILED) {
s7 = peg$parse_();
if (s7 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c27(s2, s6);
s1 = peg$c24(s6);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
return s0;
}
return s0;
}
function peg$parsestringKey() {
var s0, s1, s2;
s0 = peg$currPos;
s1 = peg$parseid();
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c28(s1);
}
s0 = s1;
if (s0 === peg$FAILED) {
function peg$parseselectFormatPattern() {
var s0, s1, s2;
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 61) {
s1 = peg$c29;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c30); }
s1 = [];
s2 = peg$parsepluralForms();
while (s2 !== peg$FAILED) {
s1.push(s2);
s2 = peg$parsepluralForms();
}
if (s1 !== peg$FAILED) {
s2 = peg$parsedigits();
peg$reportedPos = s0;
s1 = peg$c25(s1);
}
s0 = s1;
return s0;
}
function peg$parsepluralForms() {
var s0, s1, s2, s3, s4, s5, s6, s7, s8;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
s2 = peg$parsestringKey();
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c25(s2);
s0 = s1;
s3 = peg$parse_();
if (s3 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 123) {
s4 = peg$c3;
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c4); }
}
if (s4 !== peg$FAILED) {
s5 = peg$parse_();
if (s5 !== peg$FAILED) {
s6 = peg$parsemessageFormatPattern();
if (s6 !== peg$FAILED) {
s7 = peg$parse_();
if (s7 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 125) {
s8 = peg$c8;
peg$currPos++;
} else {
s8 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c9); }
}
if (s8 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c26(s2, s6);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
return s0;
}
return s0;
}
function peg$parsestring() {
var s0, s1, s2, s3, s4, s5, s6;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$currPos;
s4 = peg$parse_();
if (s4 !== peg$FAILED) {
s5 = peg$parsechars();
if (s5 !== peg$FAILED) {
s6 = peg$parse_();
if (s6 !== peg$FAILED) {
s4 = [s4, s5, s6];
s3 = s4;
function peg$parsestringKey() {
var s0, s1, s2;
s0 = peg$currPos;
s1 = peg$parseid();
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c27(s1);
}
s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 61) {
s1 = peg$c28;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c29); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parsedigits();
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c24(s2);
s0 = s1;
} else {
peg$currPos = s3;
s3 = peg$c1;
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s3;
s3 = peg$c1;
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s3;
s3 = peg$c1;
}
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$currPos;
s4 = peg$parse_();
if (s4 !== peg$FAILED) {
s5 = peg$parsechars();
if (s5 !== peg$FAILED) {
s6 = peg$parse_();
if (s6 !== peg$FAILED) {
s4 = [s4, s5, s6];
s3 = s4;
return s0;
}
function peg$parseargStylePattern() {
var s0, s1, s2, s3, s4, s5;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 44) {
s2 = peg$c6;
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c7); }
}
if (s2 !== peg$FAILED) {
s3 = peg$parse_();
if (s3 !== peg$FAILED) {
s4 = peg$parseid();
if (s4 !== peg$FAILED) {
s5 = peg$parse_();
if (s5 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c30(s4);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s3;
s3 = peg$c1;
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s3;
s3 = peg$c1;
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s3;
s3 = peg$c1;
peg$currPos = s0;
s0 = peg$c0;
}
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c31(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
return s0;
}
return s0;
}
function peg$parseid() {
var s0, s1, s2, s3, s4;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
if (peg$c32.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c33); }
function peg$parsestring() {
var s0, s1, s2;
s0 = peg$currPos;
s1 = [];
s2 = peg$parsechars();
if (s2 === peg$FAILED) {
s2 = peg$parsewhitespace();
}
if (s2 !== peg$FAILED) {
s3 = [];
if (peg$c34.test(input.charAt(peg$currPos))) {
while (s2 !== peg$FAILED) {
s1.push(s2);
s2 = peg$parsechars();
if (s2 === peg$FAILED) {
s2 = peg$parsewhitespace();
}
}
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c31(s1);
}
s0 = s1;
return s0;
}
function peg$parseid() {
var s0, s1, s2, s3, s4, s5, s6;
peg$silentFails++;
s0 = peg$currPos;
s1 = peg$parse_();
if (s1 !== peg$FAILED) {
s2 = peg$currPos;
s3 = peg$currPos;
if (peg$c33.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);

@@ -1050,91 +1235,102 @@ peg$currPos++;

s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c35); }
if (peg$silentFails === 0) { peg$fail(peg$c34); }
}
while (s4 !== peg$FAILED) {
s3.push(s4);
if (peg$c34.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
if (s4 !== peg$FAILED) {
s5 = [];
if (peg$c35.test(input.charAt(peg$currPos))) {
s6 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c35); }
s6 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c36); }
}
while (s6 !== peg$FAILED) {
s5.push(s6);
if (peg$c35.test(input.charAt(peg$currPos))) {
s6 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s6 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c36); }
}
}
if (s5 !== peg$FAILED) {
s4 = [s4, s5];
s3 = s4;
} else {
peg$currPos = s3;
s3 = peg$c0;
}
} else {
peg$currPos = s3;
s3 = peg$c0;
}
if (s3 !== peg$FAILED) {
s4 = peg$parse_();
if (s4 !== peg$FAILED) {
s3 = input.substring(s2, peg$currPos);
}
s2 = s3;
if (s2 !== peg$FAILED) {
s3 = peg$parse_();
if (s3 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c36(s2, s3);
s1 = peg$c37(s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c32); }
}
return s0;
}
return s0;
}
function peg$parsechars() {
var s0, s1, s2;
s0 = peg$currPos;
s1 = [];
s2 = peg$parsechar();
if (s2 !== peg$FAILED) {
while (s2 !== peg$FAILED) {
s1.push(s2);
s2 = peg$parsechar();
function peg$parsechars() {
var s0, s1, s2;
s0 = peg$currPos;
s1 = [];
s2 = peg$parsechar();
if (s2 !== peg$FAILED) {
while (s2 !== peg$FAILED) {
s1.push(s2);
s2 = peg$parsechar();
}
} else {
s1 = peg$c0;
}
} else {
s1 = peg$c1;
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c38(s1);
}
s0 = s1;
return s0;
}
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c37(s1);
}
s0 = s1;
return s0;
}
function peg$parsechar() {
var s0, s1, s2, s3, s4, s5;
s0 = peg$currPos;
if (peg$c38.test(input.charAt(peg$currPos))) {
s1 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c39); }
}
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c40(s1);
}
s0 = s1;
if (s0 === peg$FAILED) {
function peg$parsechar() {
var s0, s1, s2, s3, s4, s5;
s0 = peg$currPos;
if (input.substr(peg$currPos, 2) === peg$c41) {
s1 = peg$c41;
peg$currPos += 2;
if (peg$c39.test(input.charAt(peg$currPos))) {
s1 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c42); }
if (peg$silentFails === 0) { peg$fail(peg$c40); }
}
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c43();
s1 = peg$c41(s1);
}

@@ -1144,12 +1340,12 @@ s0 = s1;

s0 = peg$currPos;
if (input.substr(peg$currPos, 2) === peg$c44) {
s1 = peg$c44;
if (input.substr(peg$currPos, 2) === peg$c42) {
s1 = peg$c42;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c45); }
if (peg$silentFails === 0) { peg$fail(peg$c43); }
}
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c46();
s1 = peg$c44();
}

@@ -1159,12 +1355,12 @@ s0 = s1;

s0 = peg$currPos;
if (input.substr(peg$currPos, 2) === peg$c47) {
s1 = peg$c47;
if (input.substr(peg$currPos, 2) === peg$c45) {
s1 = peg$c45;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c48); }
if (peg$silentFails === 0) { peg$fail(peg$c46); }
}
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c49();
s1 = peg$c47();
}

@@ -1174,40 +1370,55 @@ s0 = s1;

s0 = peg$currPos;
if (input.substr(peg$currPos, 2) === peg$c50) {
s1 = peg$c50;
if (input.substr(peg$currPos, 2) === peg$c48) {
s1 = peg$c48;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c51); }
if (peg$silentFails === 0) { peg$fail(peg$c49); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parsehexDigit();
if (s2 !== peg$FAILED) {
s3 = peg$parsehexDigit();
if (s3 !== peg$FAILED) {
s4 = peg$parsehexDigit();
if (s4 !== peg$FAILED) {
s5 = peg$parsehexDigit();
if (s5 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c52(s2, s3, s4, s5);
s0 = s1;
peg$reportedPos = s0;
s1 = peg$c50();
}
s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.substr(peg$currPos, 2) === peg$c51) {
s1 = peg$c51;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c52); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parsehexDigit();
if (s2 !== peg$FAILED) {
s3 = peg$parsehexDigit();
if (s3 !== peg$FAILED) {
s4 = peg$parsehexDigit();
if (s4 !== peg$FAILED) {
s5 = peg$parsehexDigit();
if (s5 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c53(s2, s3, s4, s5);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c1;
}

@@ -1217,115 +1428,112 @@ }

}
return s0;
}
return s0;
}
function peg$parsedigits() {
var s0, s1, s2;
s0 = peg$currPos;
s1 = [];
if (peg$c53.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c54); }
}
if (s2 !== peg$FAILED) {
while (s2 !== peg$FAILED) {
s1.push(s2);
if (peg$c53.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c54); }
function peg$parsedigits() {
var s0, s1, s2;
s0 = peg$currPos;
s1 = [];
if (peg$c54.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c55); }
}
if (s2 !== peg$FAILED) {
while (s2 !== peg$FAILED) {
s1.push(s2);
if (peg$c54.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c55); }
}
}
} else {
s1 = peg$c0;
}
} else {
s1 = peg$c1;
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c56(s1);
}
s0 = s1;
return s0;
}
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c55(s1);
function peg$parsehexDigit() {
var s0;
if (peg$c57.test(input.charAt(peg$currPos))) {
s0 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c58); }
}
return s0;
}
s0 = s1;
return s0;
}
function peg$parsehexDigit() {
var s0;
if (peg$c56.test(input.charAt(peg$currPos))) {
s0 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c57); }
}
return s0;
}
function peg$parse_() {
var s0, s1, s2;
peg$silentFails++;
s0 = peg$currPos;
s1 = [];
s2 = peg$parsewhitespace();
while (s2 !== peg$FAILED) {
s1.push(s2);
function peg$parse_() {
var s0, s1, s2;
peg$silentFails++;
s0 = peg$currPos;
s1 = [];
s2 = peg$parsewhitespace();
while (s2 !== peg$FAILED) {
s1.push(s2);
s2 = peg$parsewhitespace();
}
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c60(s1);
}
s0 = s1;
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c59); }
}
return s0;
}
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c59(s1);
function peg$parsewhitespace() {
var s0;
if (peg$c61.test(input.charAt(peg$currPos))) {
s0 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c62); }
}
return s0;
}
s0 = s1;
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c58); }
}
return s0;
}
function peg$parsewhitespace() {
var s0;
if (peg$c60.test(input.charAt(peg$currPos))) {
s0 = input.charAt(peg$currPos);
peg$currPos++;
peg$result = peg$startRuleFunction();
if (peg$result !== peg$FAILED && peg$currPos === input.length) {
return peg$result;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c61); }
if (peg$result !== peg$FAILED && peg$currPos < input.length) {
peg$fail({ type: "end", description: "end of input" });
}
throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos);
}
return s0;
}
peg$result = peg$startRuleFunction();
if (peg$result !== peg$FAILED && peg$currPos === input.length) {
return peg$result;
} else {
if (peg$result !== peg$FAILED && peg$currPos < input.length) {
peg$fail({ type: "end", description: "end of input" });
}
throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos);
}
}
return {
SyntaxError: SyntaxError,
parse: parse
};
})();
MessageFormat.prototype.parse = function () {
return {
SyntaxError: SyntaxError,
parse: parse
};
})();
// Bind to itself so error handling works

@@ -1335,115 +1543,197 @@ return mparser.parse.apply( mparser, arguments );

MessageFormat.prototype.precompile = function ( ast ) {
var self = this,
needOther = false;
function _next ( data ) {
var res = JSON.parse( JSON.stringify( data ) );
res.pf_count++;
return res;
/** Utility function for quoting an Object's key value iff required
* @private */
var propname = function(key, obj) {
if (/^[A-Z_$][0-9A-Z_$]*$/i.test(key)) {
return obj ? obj + '.' + key : key;
} else {
var jkey = JSON.stringify(key);
return obj ? obj + '[' + jkey + ']' : jkey;
}
function interpMFP ( ast, data ) {
// Set some default data
data = data || { keys: {}, offset: {} };
var r = [], i, tmp;
};
switch ( ast.type ) {
case 'program':
return interpMFP( ast.program );
case 'messageFormatPattern':
for ( i = 0; i < ast.statements.length; ++i ) {
r.push(interpMFP( ast.statements[i], data ));
}
tmp = r.join('+') || '""';
return data.pf_count ? tmp : 'function(d){return ' + tmp + '}';
case 'messageFormatPatternRight':
for ( i = 0; i < ast.statements.length; ++i ) {
r.push(interpMFP( ast.statements[i], data ));
}
return r.join('+');
case 'messageFormatElement':
data.pf_count = data.pf_count || 0;
if ( ast.output ) {
return self.globalName + '.v(d,"' + ast.argumentIndex + '")';
}
else {
data.keys[data.pf_count] = '"' + ast.argumentIndex + '"';
return interpMFP( ast.elementFormat, data );
}
return '';
case 'elementFormat':
if ( ast.key === 'select' ) {
return self.globalName + '.s(d,' + data.keys[data.pf_count] + ',' + interpMFP( ast.val, data ) + ')';
}
else if ( ast.key === 'plural' ) {
/** Recursively map an AST to its resulting string
* @private */
MessageFormat.prototype._precompile = function(ast, data) {
data = data || { keys: {}, offset: {} };
var r = [], i, tmp, args = [];
switch ( ast.type ) {
case 'messageFormatPattern':
for ( i = 0; i < ast.statements.length; ++i ) {
r.push(this._precompile( ast.statements[i], data ));
}
tmp = r.join(' + ') || '""';
return data.pf_count ? tmp : 'function(d) { return ' + tmp + '; }';
case 'messageFormatElement':
data.pf_count = data.pf_count || 0;
if ( ast.output ) {
return propname(ast.argumentIndex, 'd');
}
else {
data.keys[data.pf_count] = ast.argumentIndex;
return this._precompile( ast.elementFormat, data );
}
return '';
case 'elementFormat':
var args = [ propname(data.keys[data.pf_count], 'd') ];
switch (ast.key) {
case 'select':
args.push(this._precompile(ast.val, data));
return 'select(' + args.join(', ') + ')';
case 'selectordinal':
args = args.concat([ 0, propname(this.lc[0], 'pluralFuncs'), this._precompile(ast.val, data), 1 ]);
return 'plural(' + args.join(', ') + ')';
case 'plural':
data.offset[data.pf_count || 0] = ast.val.offset || 0;
return self.globalName + '.p(d,' + data.keys[data.pf_count] + ',' + (data.offset[data.pf_count] || 0)
+ ',"' + self.lc + '",' + interpMFP( ast.val, data ) + ')';
}
return '';
/* // Unreachable cases.
case 'pluralStyle':
case 'selectStyle':*/
case 'pluralFormatPattern':
data.pf_count = data.pf_count || 0;
needOther = true;
// We're going to simultaneously check to make sure we hit the required 'other' option.
args = args.concat([ data.offset[data.pf_count] || 0, propname(this.lc[0], 'pluralFuncs'), this._precompile(ast.val, data) ]);
return 'plural(' + args.join(', ') + ')';
default:
if (this.withIntlSupport && !(ast.key in this.runtime.fmt) && (ast.key in MessageFormat.formatters)) {
tmp = MessageFormat.formatters[ast.key];
this.runtime.fmt[ast.key] = (typeof tmp(this) == 'function') ? tmp(this) : tmp;
}
args.push(JSON.stringify(this.lc));
if (ast.val && ast.val.length) args.push(JSON.stringify(ast.val.length == 1 ? ast.val[0] : ast.val));
return 'fmt.' + ast.key + '(' + args.join(', ') + ')';
}
for ( i = 0; i < ast.pluralForms.length; ++i ) {
if ( ast.pluralForms[ i ].key === 'other' ) {
needOther = false;
}
r.push('"' + ast.pluralForms[ i ].key + '":' + interpMFP( ast.pluralForms[ i ].val, _next(data) ));
case 'pluralFormatPattern':
case 'selectFormatPattern':
data.pf_count = data.pf_count || 0;
if (ast.type == 'selectFormatPattern') data.offset[data.pf_count] = 0;
var needOther = true;
for ( i = 0; i < ast.pluralForms.length; ++i ) {
var key = ast.pluralForms[i].key;
if ( key === 'other' ) {
needOther = false;
}
if ( needOther ) {
throw new Error("No 'other' form found in pluralFormatPattern " + data.pf_count);
}
return '{' + r.join(',') + '}';
case 'selectFormatPattern':
var data_copy = JSON.parse(JSON.stringify(data));
data_copy.pf_count++;
r.push(propname(key) + ': ' + this._precompile(ast.pluralForms[i].val, data_copy));
}
if ( needOther ) {
throw new Error("No 'other' form found in " + ast.type + " " + data.pf_count);
}
return '{ ' + r.join(', ') + ' }';
data.pf_count = data.pf_count || 0;
data.offset[data.pf_count] = 0;
needOther = true;
case 'string':
tmp = '"' + (ast.val || "").replace(/\n/g, '\\n').replace(/"/g, '\\"') + '"';
if ( data.pf_count ) {
args = [ propname(data.keys[data.pf_count-1], 'd') ];
if (data.offset[data.pf_count-1]) args.push(data.offset[data.pf_count-1]);
tmp = tmp.replace(/(^|[^\\])#/g, '$1"+' + 'number(' + args.join(', ') + ')+"');
tmp = tmp.replace(/^""\+/, '').replace(/\+""$/, '');
}
return tmp;
for ( i = 0; i < ast.pluralForms.length; ++i ) {
if ( ast.pluralForms[ i ].key === 'other' ) {
needOther = false;
}
r.push('"' + ast.pluralForms[ i ].key + '":' + interpMFP( ast.pluralForms[ i ].val, _next(data) ));
}
if ( needOther ) {
throw new Error("No 'other' form found in selectFormatPattern " + data.pf_count);
}
return '{' + r.join(',') + '}';
/* // Unreachable
case 'pluralForms':
*/
case 'string':
tmp = '"' + (ast.val || "").replace(/\n/g, '\\n').replace(/"/g, '\\"') + '"';
if ( data.pf_count ) {
var o = data.offset[data.pf_count-1];
tmp = tmp.replace(/(^|[^\\])#/g, '$1"+' + self.globalName + '.n(d,' + data.keys[data.pf_count-1] + (o ? ',' + o : '') + ')+"');
tmp = tmp.replace(/^""\+/, '').replace(/\+""$/, '');
}
return tmp;
default:
throw new Error( 'Bad AST type: ' + ast.type );
}
default:
throw new Error( 'Bad AST type: ' + ast.type );
}
return interpMFP( ast );
};
MessageFormat.prototype.compile = function ( message ) {
return (new Function(
'this[\'' + this.globalName + '\']=' + this.functions() + ';' +
'return ' + this.precompile( this.parse( message ))
))();
};
/**
* Compile messages into an executable function with clean string
* representation.
*
* If `messages` is a single string including ICU MessageFormat declarations,
* `opt` is ignored and the returned function takes a single Object parameter
* `d` representing each of the input's defined variables. The returned
* function will be defined in a local scope that includes all the required
* runtime variables.
*
* If `messages` is a map of keys to strings, or a map of namespace keys to
* such key/string maps, the returned function will fill the specified global
* with javascript functions matching the structure of the input. In such use,
* the output of `compile()` is expected to be serialized using `.toString()`,
* and will include definitions of the runtime functions.
*
* Together, the input parameters should match the following patterns:
* ```js
* messages = "string" || { key0: "string0", key1: "string1", ... } || {
* ns0: { key0: "string0", key1: "string1", ... },
* ns1: { key0: "string0", key1: "string1", ... },
* ...
* }
*
* opt = null || {
* locale: null || {
* ns0: "lc0" || [ "lc0", ... ],
* ns1: "lc1" || [ "lc1", ... ],
* ...
* },
* global: null || "module.exports" || "exports" || "i18n" || ...
* }
* ```
*
* @memberof MessageFormat
* @param {string|Object}
* messages - The input message(s) to be compiled, in ICU MessageFormat
* @param {Object} [opt={}] - Options controlling output for non-simple intput
* @param {Object} [opt.locale] - The locales to use for the messages, with a
* structure matching that of `messages`
* @param {string} [opt.global=""] - The global variable that the output
* function should use, or a null string for none. "exports" and
* "module.exports" are recognised as special cases.
* @returns {function} The first match found for the given locale(s)
*/
MessageFormat.prototype.compile = function ( messages, opt ) {
var r = {}, lc0 = this.lc,
compileMsg = function(self, msg) {
try {
var ast = MessageFormat._parse(msg);
return self._precompile(ast);
} catch (e) {
throw new Error((ast ? 'Precompiler' : 'Parser') + ' error: ' + e.toString());
}
},
stringify = function(r, level) {
if (!level) level = 0;
if (typeof r != 'object') return r;
var o = [], indent = '';
for (var i = 0; i < level; ++i) indent += ' ';
for (var k in r) o.push('\n' + indent + ' ' + propname(k) + ': ' + stringify(r[k], level + 1));
return '{' + o.join(',') + '\n' + indent + '}';
};
MessageFormat.prototype.precompileObject = function ( messages ) {
var tmp = [];
for (var key in messages) {
tmp.push(JSON.stringify(key) + ':' + this.precompile(this.parse(messages[key])));
if (typeof messages == 'string') {
var f = new Function(
'number, plural, select, pluralFuncs, fmt',
'return ' + compileMsg(this, messages));
return f(this.runtime.number, this.runtime.plural, this.runtime.select,
this.runtime.pluralFuncs, this.runtime.fmt);
}
return '{\n' + tmp.join(',\n') + '}';
opt = opt || {};
for (var ns in messages) {
if (opt.locale) this.lc = opt.locale[ns] && [].concat(opt.locale[ns]) || lc0;
if (typeof messages[ns] == 'string') {
try { r[ns] = compileMsg(this, messages[ns]); }
catch (e) { e.message = e.message.replace(':', ' with `' + ns + '`:'); throw e; }
} else {
r[ns] = {};
for (var key in messages[ns]) {
try { r[ns][key] = compileMsg(this, messages[ns][key]); }
catch (e) { e.message = e.message.replace(':', ' with `' + key + '` in `' + ns + '`:'); throw e; }
}
}
}
this.lc = lc0;
var s = this.runtime.toString() + '\n';
switch (opt.global || '') {
case 'exports':
var o = [];
for (var k in r) o.push(propname(k, 'exports') + ' = ' + stringify(r[k]));
return new Function(s + o.join(';\n'));
case 'module.exports':
return new Function(s + 'module.exports = ' + stringify(r));
case '':
return new Function(s + 'return ' + stringify(r));
default:
return new Function('G', s + propname(opt.global, 'G') + ' = ' + stringify(r));
}
};

@@ -1459,3 +1749,3 @@

else if (typeof define === 'function' && define.amd) {
define(function() {
define(['make-plural'], function() {
return MessageFormat;

@@ -1462,0 +1752,0 @@ });

{
"name": "messageformat",
"version": "0.2.1",
"author": "Alex Sexton <alexsexton@gmail.com>",
"version": "0.3.0-0",
"description": "PluralFormat and SelectFormat Message and i18n Tool - A JavaScript Implemenation of the ICU standards.",
"repository": {
"type": "git",
"url": "https://SlexAxton@github.com/SlexAxton/messageformat.js.git"
},
"scripts": {
"test": "bin/messageformat.js --module --locale en --include example/en/colors.json -o test/common-js-generated-test-fixture.js; mocha --require test/common --reporter spec --growl test/tests.js"
},
"main": "./messageformat",
"bin": {
"messageformat": "./bin/messageformat.js"
},
"contributors":[
"Eemeli Aro <eemeli@gmail.com>"
],
"keywords": [

@@ -30,17 +15,38 @@ "i18n",

],
"author": "Alex Sexton <alexsexton@gmail.com>",
"contributors": [
"Eemeli Aro <eemeli@gmail.com>"
],
"license": "To use or fork, MIT License. To contribute back, Dojo CLA",
"homepage": "https://github.com/SlexAxton/messageformat.js",
"repository": {
"type": "git",
"url": "https://github.com/SlexAxton/messageformat.js.git"
},
"main": "./messageformat",
"bin": { "messageformat": "./bin/messageformat.js" },
"files": [
"messageformat.js",
"bin/messageformat.js",
"example",
"LICENSE",
"README.md"
],
"dependencies": {
"async": "~0.2.10",
"glob": "~3.2.8",
"make-plural": "~2.1.1",
"nopt": "~2.1.2",
"coffee-script": "~1.7.0",
"watchr": "~2.4.9",
"underscore": "~1.5.2",
"async": "~0.2.10",
"glob": "~3.2.8"
"watchr": "~2.4.9"
},
"devDependencies": {
"expect.js": "*",
"jsdoc": "^3.3.0-beta1",
"mocha": "*",
"expect.js": "*",
"serve": "*",
"pegjs": "*"
"pegjs": "*",
"serve": "*"
},
"license": "To use or fork, Apache License, Version 2.0. To contribute back, Dojo CLA"
"scripts": {
"test": "make test"
}
}

@@ -140,14 +140,39 @@ [![Build Status](https://secure.travis-ci.org/SlexAxton/messageformat.js.png)](http://travis-ci.org/SlexAxton/messageformat.js)

I will eventually release a Handlebars and Require.js (r.js) plugin to do this automatically, but if you would like to output the raw javascript function, the following does that:
I will eventually release a Handlebars and Require.js (r.js) plugin to do this automatically. For now you can grab the raw javascript function the following way:
```javascript
var mf = new MessageFormat('en');
var js_string_represenation = mf.precompile(
mf.parse(
'Your {NUM, plural, one{message} other{messages}} go here.'
)
);
> var mf = new MessageFormat('en');
> var messages = {
simple: 'A simple message.',
var: 'Message with {X}.',
plural: 'You have {N, plural, =0{no messages} one{1 message} other{# messages}}.',
select: '{GENDER, select, male{He has} female{She has} other{They have}} sent you a message.',
ordinal: 'The {N, selectordinal, one{1st} two{2nd} few{3rd} other{#th}} message.' };
// This returns an unnamed - unreferenced function that needs to be passed the
// MessageFormat object. See the source of `MessageFormat.compile` for more details.
> var vfunc = mf.compile(messages.var);
> vfunc({X:'a variable'})
'Message with a variable.'
> vfunc.toString()
'function (d){return "Message with "+d["X"]+"."}'
> var mfunc = mf.compile(messages);
> mfunc().ordinal({N:3})
'The 3rd message.'
> console.log(mfunc.toString())
function anonymous() {
var
n=function(v,o){ if (isNaN(v)) throw new Error("'"+v+"' isn't a number."); return v - (o||0) },
p=function(v,o,l,p,s){ return v in p ? p[v] : ( v = l(o ? v-o : v, s), v in p ? p[v] : p.other ) },
s=function(v,p){ return v in p ? p[v] : p.other },
pf={"en":function(n,ord) { var s = String(n).split('.'), v0 = !s[1], t0 = Number(s[0]) == n, n10 = t0 && s[0].substr(-1), n100 = t0 && s[0].substr(-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'; }},
fmt={};
return {
simple:function(d){return "A simple message."},
var:function(d){return "Message with "+d["X"]+"."},
plural:function(d){return "You have "+p(d["N"],0,pf["en"],{0:"no messages",one:"1 message",other:n(d["N"])+" messages"})+"."},
select:function(d){return s(d["GENDER"],{male:"He has",female:"She has",other:"They have"})+" sent you a message."},
ordinal:function(d){return "The "+p(d["N"],0,pf["en"],{one:"1st",two:"2nd",few:"3rd",other:n(d["N"])+"th"},1)+" message."}}
}
```

@@ -419,4 +444,4 @@

'You {NUM_ADDS, plural, offset:1' +
'=0{didnt add this to your profile}' + // Number literals, with a `=` do **NOT** use
'zero{added this to your profile}' + // the offset value
'=0{didnt add this to your profile}' + // Number literals, with a `=` do **NOT** use
'=1{added this to your profile}' + // the offset value
'one{and one other person added this to their profile}' +

@@ -440,3 +465,3 @@ 'other{and # others added this to their profiles}' +

> message({"NUM_ADDS" : 3 });
"You and 3 others added this to their profile."
"You and 2 others added this to their profile."

@@ -501,6 +526,7 @@ ```

`0.1.8`
`0.3.0-0`
## TODO
* Update the documentation
* Create a tool to help translators understand and use this format.

@@ -511,3 +537,3 @@ * Template integration - I specifically want to make a build time handlebars.js plugin to build this logic into the template builds.

You may use this software under the Apache License, version 2.0.
You may use this software under the MIT License.

@@ -532,1 +558,5 @@ You may contribute to this software under the Dojo CLA - <http://dojofoundation.org/about/cla>

* Norbert Lindenberg for showing me how good it can be.
## Implementations in other languages
[Jeff Hansen](https://github.com/jeffijoe) ([@jeffijoe](https://twitter.com/jeffijoe)) wrote an implementation for .NET: https://github.com/jeffijoe/messageformat.net - it's a Portable Class Library, making it possible to use on iOS, Android, Windows Phone, and pretty much any other .NET target.

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc