make-plural
Advanced tools
Comparing version 2.1.3 to 3.0.0-rc1
@@ -0,4 +1,14 @@ | ||
"use strict"; | ||
var _toArray = function (arr) { return Array.isArray(arr) ? arr : Array.from(arr); }; | ||
var _toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; | ||
var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; | ||
/** | ||
* make-plural.js -- https://github.com/eemeli/make-plural.js/ | ||
* Copyright (c) 2014 by Eemeli Aro <eemeli@gmail.com> | ||
* Copyright (c) 2014-2015 by Eemeli Aro <eemeli@gmail.com> | ||
* | ||
@@ -18,199 +28,272 @@ * Permission to use, copy, modify, and/or distribute this software for any | ||
(function (global) { | ||
var Parser = (function () { | ||
function Parser() { | ||
_classCallCheck(this, Parser); | ||
} | ||
function parse(cond, symbols) { | ||
if (cond == 'i = 0 or n = 1') return 'n >= 0 && n <= 1'; | ||
if (cond == 'i = 0,1') return 'n >= 0 && n < 2'; | ||
if (cond == 'i = 1 and v = 0') { | ||
symbols['v0'] = 1; | ||
return 'n == 1 && v0'; | ||
} | ||
return cond | ||
.replace(/([tv]) (!?)= 0/g, function(m, sym, noteq) { | ||
var sn = sym + '0'; | ||
symbols[sn] = 1; | ||
return noteq ? '!' + sn : sn; | ||
}) | ||
.replace(/\b[fintv]\b/g, function(m) { | ||
symbols[m] = 1; | ||
return m; | ||
}) | ||
.replace(/([fin]) % (10+)/g, function(m, sym, num) { | ||
var sn = sym + num; | ||
symbols[sn] = 1; | ||
return sn; | ||
}) | ||
.replace(/n10+ = 0/g, 't0 && $&') | ||
.replace(/(\w+ (!?)= )([0-9.]+,[0-9.,]+)/g, function(m, se, noteq, x) { | ||
if (m == 'n = 0,1') return '(n == 0 || n == 1)'; | ||
if (noteq) return se + x.split(',').join(' && ' + se); | ||
return '(' + se + x.split(',').join(' || ' + se) + ')'; | ||
}) | ||
.replace(/(\w+) (!?)= ([0-9]+)\.\.([0-9]+)/g, function(m, sym, noteq, x0, x1) { | ||
if (Number(x0) + 1 == Number(x1)) { | ||
if (noteq) return sym + ' != ' + x0 + ' && ' + sym + ' != ' + x1; | ||
return '(' + sym + ' == ' + x0 + ' || ' + sym + ' == ' + x1 + ')'; | ||
} | ||
if (noteq) return '(' + sym + ' < ' + x0 + ' || ' + sym + ' > ' + x1 + ')'; | ||
if (sym == 'n') { symbols['t0'] = 1; return '(t0 && n >= ' + x0 + ' && n <= ' + x1 + ')'; } | ||
return '(' + sym + ' >= ' + x0 + ' && ' + sym + ' <= ' + x1 + ')'; | ||
}) | ||
.replace(/ and /g, ' && ') | ||
.replace(/ or /g, ' || ') | ||
.replace(/ = /g, ' == '); | ||
} | ||
_createClass(Parser, { | ||
parse: { | ||
value: function parse(cond) { | ||
var _this = this; | ||
function vars(symbols) { | ||
var vars = []; | ||
if (symbols['i']) vars.push("i = s[0]"); | ||
if (symbols['f'] || symbols['v']) vars.push("f = s[1] || ''"); | ||
if (symbols['t']) vars.push("t = (s[1] || '').replace(/0+$/, '')"); | ||
if (symbols['v']) vars.push("v = f.length") | ||
if (symbols['v0']) vars.push("v0 = !s[1]"); | ||
if (symbols['t0'] || symbols['n10'] || symbols['n100']) vars.push("t0 = Number(s[0]) == n"); | ||
for (var k in symbols) if (/^.10+$/.test(k)) { | ||
var k0 = (k[0] == 'n') ? 't0 && s[0]' : k[0]; | ||
vars.push(k + ' = ' + k0 + '.slice(-' + k.substr(2).length + ')'); | ||
} | ||
if (vars.length) { | ||
vars.unshift("s = String(n).split('.')"); | ||
return 'var ' + vars.join(', ') + ';'; | ||
} | ||
return ''; | ||
} | ||
if (cond == "i = 0 or n = 1") { | ||
return "n >= 0 && n <= 1"; | ||
}if (cond == "i = 0,1") { | ||
return "n >= 0 && n < 2"; | ||
}if (cond == "i = 1 and v = 0") { | ||
this.v0 = 1; | ||
return "n == 1 && v0"; | ||
} | ||
return cond.replace(/([tv]) (!?)= 0/g, function (m, sym, noteq) { | ||
var sn = sym + "0"; | ||
_this[sn] = 1; | ||
return noteq ? "!" + sn : sn; | ||
}).replace(/\b[fintv]\b/g, function (m) { | ||
_this[m] = 1; | ||
return m; | ||
}).replace(/([fin]) % (10+)/g, function (m, sym, num) { | ||
var sn = sym + num; | ||
_this[sn] = 1; | ||
return sn; | ||
}).replace(/n10+ = 0/g, "t0 && $&").replace(/(\w+ (!?)= )([0-9.]+,[0-9.,]+)/g, function (m, se, noteq, x) { | ||
if (m == "n = 0,1") return "(n == 0 || n == 1)"; | ||
if (noteq) return se + x.split(",").join(" && " + se); | ||
return "(" + se + x.split(",").join(" || " + se) + ")"; | ||
}).replace(/(\w+) (!?)= ([0-9]+)\.\.([0-9]+)/g, function (m, sym, noteq, x0, x1) { | ||
if (Number(x0) + 1 == Number(x1)) { | ||
if (noteq) return "" + sym + " != " + x0 + " && " + sym + " != " + x1; | ||
return "(" + sym + " == " + x0 + " || " + sym + " == " + x1 + ")"; | ||
} | ||
if (noteq) return "(" + sym + " < " + x0 + " || " + sym + " > " + x1 + ")"; | ||
if (sym == "n") { | ||
_this.t0 = 1;return "(t0 && n >= " + x0 + " && n <= " + x1 + ")"; | ||
} | ||
return "(" + sym + " >= " + x0 + " && " + sym + " <= " + x1 + ")"; | ||
}).replace(/ and /g, " && ").replace(/ or /g, " || ").replace(/ = /g, " == "); | ||
} | ||
}, | ||
vars: { | ||
value: function vars() { | ||
var vars = []; | ||
if (this.i) vars.push("i = s[0]"); | ||
if (this.f || this.v) vars.push("f = s[1] || ''"); | ||
if (this.t) vars.push("t = (s[1] || '').replace(/0+$/, '')"); | ||
if (this.v) vars.push("v = f.length"); | ||
if (this.v0) vars.push("v0 = !s[1]"); | ||
if (this.t0 || this.n10 || this.n100) vars.push("t0 = Number(s[0]) == n"); | ||
for (var k in this) { | ||
if (/^.10+$/.test(k)) { | ||
var k0 = k[0] == "n" ? "t0 && s[0]" : k[0]; | ||
vars.push("" + k + " = " + k0 + ".slice(-" + k.substr(2).length + ")"); | ||
} | ||
}if (!vars.length) { | ||
return ""; | ||
}return "var " + ["s = String(n).split('.')"].concat(vars).join(", "); | ||
} | ||
} | ||
}); | ||
function build(lc, opt, tests) { | ||
var lines = [], symbols = {}, | ||
_fold = function(l) { return l.replace(/(.{1,72})( \|\| |$) ?/gm, '$1\n $2').replace(/\s+$/gm, ''); }, | ||
_compile = function(type, req) { | ||
var cases = []; | ||
if (!MakePlural.rules || !MakePlural.rules[type]) { | ||
MakePlural.load((type == 'ordinal') | ||
? './data/unicode-cldr-ordinal-rules.json' | ||
: './data/unicode-cldr-plural-rules.json'); | ||
} | ||
if (MakePlural.rules[type][lc]) { | ||
for (var r in MakePlural.rules[type][lc]) { | ||
var key = r.replace('pluralRule-count-', ''), | ||
parts = MakePlural.rules[type][lc][r].split(/@\w*/), | ||
cond = parts.shift().trim(); | ||
if (cond) cases.push([parse(cond, symbols), key]); | ||
tests[type][key] = parts.join(' ') | ||
.replace(/^[ ,]+|[ ,…]+$/g, '') | ||
.replace(/(0\.[0-9])~(1\.[1-9])/g, '$1 1.0 $2') | ||
.split(/[ ,~…]+/); | ||
} | ||
} else if (req) { | ||
if (!opt['quiet']) console.error('Locale "' + lc + '" ' + type + ' rules not found'); | ||
return false; | ||
} | ||
if (!cases.length) return "'other'"; | ||
if (cases.length == 1) return "(" + cases[0][0] + ") ? '" + cases[0][1] + "' : 'other'"; | ||
return cases.map(function(c) { return "(" + c[0] + ") ? '" + c[1] + "'"; }).concat("'other'").join('\n : '); | ||
}; | ||
return Parser; | ||
})(); | ||
if (opt['ordinals']) { | ||
if (opt['no_cardinals']) { | ||
var l = _compile('ordinal', true); | ||
if (!l) return null; | ||
lines.push(_fold(' return ' + l + ';')); | ||
} else { | ||
lines.push(_fold(' if (ord) return ' + _compile('ordinal', false) + ';')); | ||
} | ||
} | ||
if (!opt['no_cardinals']) { | ||
var l = _compile('cardinal', true); | ||
if (!l) return null; | ||
lines.push(_fold(' return ' + l + ';')); | ||
} | ||
var fn_vars = vars(symbols).replace(/(.{1,78})(,|$) ?/g, '\n $1$2').trim(); | ||
if (fn_vars) lines.unshift(' ' + fn_vars); | ||
return lines.join('\n'); | ||
} | ||
var Rules = (function () { | ||
function Rules() { | ||
_classCallCheck(this, Rules); | ||
function test(lc, fn, tests, opt) { | ||
var ok = true, | ||
_test = function(k, x, ord) { | ||
try { var r = fn(x, ord); } | ||
catch (e) { r = e.toString(); } | ||
if (r != k) { | ||
ok = false; | ||
if (!opt['quiet']) console.error( | ||
'Locale "' + lc + '" ' + (ord ? 'ordinal' : 'cardinal') | ||
+ ' rule self-test failed for v = ' | ||
+ (typeof x == 'string' ? '"' + x + '"' : x) | ||
+ ' (was "' + r + '", expected "' + k + '")' | ||
); | ||
return false; | ||
} | ||
return true; | ||
}; | ||
for (var t in tests) { | ||
var ord = (t == 'ordinal'); | ||
for (var k in tests[t]) { | ||
tests[t][k].forEach(function(v) { | ||
if (_test(k, v, ord) && !/\.0+$/.test(v)) _test(k, Number(v), ord); | ||
}); | ||
} | ||
} | ||
return ok; | ||
} | ||
this.data = {}; | ||
this.rootPath = "./data/"; | ||
} | ||
function xhr_require(src, url) { | ||
if (src && (url[0] == '.')) url = src.replace(/[^\/]*$/, url); | ||
var xhr = new XMLHttpRequest(); | ||
xhr.open('get', url, false); | ||
xhr.send(); | ||
return (xhr.status == 200) && JSON.parse(xhr.responseText); | ||
} | ||
_createClass(Rules, { | ||
loadData: { | ||
value: function loadData(cldr) { | ||
var data = cldr && cldr.supplemental || {}; | ||
return this.data = { | ||
cardinal: data["plurals-type-cardinal"] || this.data.cardinal, | ||
ordinal: data["plurals-type-ordinal"] || this.data.ordinal | ||
}; | ||
} | ||
}, | ||
loadPath: { | ||
value: function loadPath(path) { | ||
if (path.indexOf("/") == -1) path = this.rootPath + path; | ||
if (typeof require == "function") { | ||
return this.loadData(require(path)); | ||
} | ||
var xhr = new XMLHttpRequest(); | ||
xhr.open("get", path, false); | ||
xhr.send(); | ||
if (xhr.status != 200) throw new Error("XMLHttpRequest failed for " + JSON.stringify(path)); | ||
return this.loadData(JSON.parse(xhr.responseText)); | ||
} | ||
}, | ||
cardinal: { | ||
get: function () { | ||
return this.data.cardinal || this.loadPath("unicode-cldr-plural-rules.json").cardinal; | ||
} | ||
}, | ||
ordinal: { | ||
get: function () { | ||
return this.data.ordinal || this.loadPath("unicode-cldr-ordinal-rules.json").ordinal; | ||
} | ||
} | ||
}); | ||
return Rules; | ||
})(); | ||
var MakePlural = function(lc, opt) { | ||
if (typeof lc == 'object') { opt = lc; lc = opt.lc; } | ||
else { | ||
if (!opt) opt = MakePlural.opt; | ||
if (!lc) lc = opt.lc; | ||
} | ||
var tests = { 'ordinal':{}, 'cardinal':{} }, | ||
fn_body = build(lc, opt, tests), | ||
fn = opt['ordinals'] && !opt['no_cardinals'] | ||
? new Function('n', 'ord', fn_body) | ||
: new Function('n', fn_body); | ||
fn.toString = function(name) { | ||
var s = Function.prototype.toString.call(fn); | ||
return s.replace(/^function( \w+)?/, name ? 'function ' + name : 'function'); | ||
}; | ||
return fn_body && (opt['no_tests'] || test(lc, fn, tests, opt)) ? fn : null; | ||
}; | ||
var Tests = (function () { | ||
function Tests(obj) { | ||
_classCallCheck(this, Tests); | ||
MakePlural.opt = {}; | ||
MakePlural.rules = {}; | ||
this.obj = obj; | ||
this.ordinal = {}; | ||
this.cardinal = {}; | ||
} | ||
MakePlural.load = function(/* arguments */) { | ||
var _require = (typeof require == 'function') ? require : function(url) { return xhr_require(MakePlural.src_url, url); }; | ||
if (!MakePlural.rules) MakePlural.rules = {}; | ||
for (var i = 0; i < arguments.length; ++i) { | ||
var cldr = (typeof arguments[i] == 'string') ? _require(arguments[i]) : arguments[i]; | ||
if (cldr && cldr['supplemental']) ['cardinal', 'ordinal'].forEach(function(type) { | ||
var set = cldr['supplemental']['plurals-type-' + type]; | ||
if (set) MakePlural.rules[type] = set; | ||
}); | ||
} | ||
return MakePlural; | ||
}; | ||
_createClass(Tests, { | ||
add: { | ||
value: function add(type, cat, examples) { | ||
this[type][cat] = examples.join(" ").replace(/^[ ,]+|[ ,…]+$/g, "").replace(/(0\.[0-9])~(1\.[1-9])/g, "$1 1.0 $2").split(/[ ,~…]+/); | ||
} | ||
}, | ||
testCond: { | ||
value: function testCond(n, type, expResult) { | ||
try { | ||
var r = this.obj.fn(n, type == "ordinal"); | ||
} catch (e) { | ||
r = e.toString(); | ||
} | ||
if (r != expResult) throw new Error("Locale " + JSON.stringify(this.obj.lc) + type + " rule self-test failed for v = " + JSON.stringify(n) + " (was " + JSON.stringify(r) + ", expected " + JSON.stringify(expResult) + ")"); | ||
return true; | ||
} | ||
}, | ||
testCat: { | ||
value: function testCat(type, cat) { | ||
var _this = this; | ||
this[type][cat].forEach(function (n) { | ||
_this.testCond(n, type, cat); | ||
/\.0+$/.test(n) || _this.testCond(Number(n), type, cat); | ||
}); | ||
return true; | ||
} | ||
}, | ||
testAll: { | ||
value: function testAll() { | ||
for (var cat in this.cardinal) { | ||
this.testCat("cardinal", cat); | ||
}for (var cat in this.ordinal) { | ||
this.testCat("ordinal", cat); | ||
}return true; | ||
} | ||
} | ||
}); | ||
if ((typeof module !== 'undefined') && module.exports) { | ||
module.exports = MakePlural; | ||
} else if (typeof exports !== 'undefined') { | ||
for (var p in MakePlural) exports[p] = MakePlural[p]; | ||
exports.get = MakePlural; | ||
} else if (typeof define !== 'undefined' && define.amd) { | ||
define(function() { return MakePlural; }); | ||
} else { | ||
try { MakePlural.src_url = Array.prototype.slice.call(document.getElementsByTagName('script')).pop().src; } | ||
catch (e) { MakePlural.src_url = ''; } | ||
global.MakePlural = MakePlural; | ||
} | ||
return Tests; | ||
})(); | ||
})(this); | ||
var MakePlural = (function () { | ||
function MakePlural(lc) { | ||
var opt = arguments[1] === undefined ? {} : arguments[1]; | ||
_classCallCheck(this, MakePlural); | ||
if (typeof lc == "object") { | ||
opt = lc; | ||
lc = opt.lc; | ||
} | ||
this.lc = lc || MakePlural.lc; | ||
this.cardinals = opt.cardinals || MakePlural.cardinals; | ||
this.ordinals = opt.ordinals || MakePlural.ordinals; | ||
if (!this.ordinals && !this.cardinals) throw new Error("At least one type of plural is required"); | ||
this.parser = new Parser(); | ||
this.tests = new Tests(this); | ||
this.fn = this.buildFunction(); | ||
this.fn.obj = this; | ||
this.fn.test = (function () { | ||
return this.tests.testAll() && this.fn; | ||
}).bind(this); | ||
this.fn.toString = this.fnToString.bind(this); | ||
return this.fn; | ||
} | ||
_createClass(MakePlural, { | ||
compile: { | ||
value: function compile(type, req) { | ||
var cases = []; | ||
var rules = MakePlural.rules[type][this.lc]; | ||
if (!rules) { | ||
if (req) throw new Error("Locale \"" + this.lc + "\" " + type + " rules not found"); | ||
return "'other'"; | ||
} | ||
for (var r in rules) { | ||
var _rules$r$trim$split = rules[r].trim().split(/\s*@\w*/); | ||
var _rules$r$trim$split2 = _toArray(_rules$r$trim$split); | ||
var cond = _rules$r$trim$split2[0]; | ||
var examples = _rules$r$trim$split2.slice(1); | ||
var cat = r.replace("pluralRule-count-", ""); | ||
if (cond) cases.push([this.parser.parse(cond), cat]); | ||
this.tests.add(type, cat, examples); | ||
} | ||
if (cases.length == 1) { | ||
return "(" + cases[0][0] + ") ? '" + cases[0][1] + "' : 'other'"; | ||
} else { | ||
return [].concat(_toConsumableArray(cases.map(function (c) { | ||
return "(" + c[0] + ") ? '" + c[1] + "'"; | ||
})), ["'other'"]).join("\n : "); | ||
} | ||
} | ||
}, | ||
buildFunction: { | ||
value: function buildFunction() { | ||
var _this = this; | ||
var compile = function (c) { | ||
var _ref; | ||
return c ? (c[1] ? "return " : "if (ord) return ") + (_ref = _this).compile.apply(_ref, _toConsumableArray(c)) : ""; | ||
}, | ||
fold = { vars: function (str) { | ||
return (" " + str + ";").replace(/(.{1,78})(,|$) ?/g, "$1$2\n "); | ||
}, | ||
cond: function (str) { | ||
return (" " + str + ";").replace(/(.{1,78}) (\|\| |$) ?/gm, "$1\n $2"); | ||
} }, | ||
cond = [this.ordinals && ["ordinal", !this.cardinals], this.cardinals && ["cardinal", true]].map(compile).map(fold.cond), | ||
body = [fold.vars(this.parser.vars())].concat(_toConsumableArray(cond)).join("\n").replace(/\s+$/gm, "").replace(/^[\s;]*[\r\n]+/gm, ""), | ||
args = this.ordinals && this.cardinals ? "n, ord" : "n"; | ||
return new Function(args, body); | ||
} | ||
}, | ||
fnToString: { | ||
value: function fnToString(name) { | ||
return Function.prototype.toString.call(this.fn).replace(/^function( \w+)?/, name ? "function " + name : "function").replace("\n/**/", ""); | ||
} | ||
} | ||
}, { | ||
load: { | ||
value: function load() { | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
args.forEach(function (arg) { | ||
if (typeof arg == "string") MakePlural.rules.loadPath(arg);else MakePlural.rules.loadData(arg); | ||
}); | ||
return MakePlural; | ||
} | ||
} | ||
}); | ||
return MakePlural; | ||
})(); | ||
if (typeof module !== "undefined") module.exports = MakePlural; | ||
MakePlural.cardinals = true; | ||
MakePlural.ordinals = false; | ||
MakePlural.rules = new Rules(); | ||
{ | ||
"name": "make-plural", | ||
"version": "2.1.3", | ||
"version": "3.0.0-rc1", | ||
"description": "Translates Unicode CLDR pluralization rules to executable JavaScript", | ||
"keywords": ["unicode", "cldr", "i18n", "internationalization", "pluralization"], | ||
"keywords": [ | ||
"unicode", | ||
"cldr", | ||
"i18n", | ||
"internationalization", | ||
"pluralization" | ||
], | ||
"author": "Eemeli Aro <eemeli@gmail.com>", | ||
"license": "ISC", | ||
"homepage": "https://github.com/eemeli/make-plural.js", | ||
"repository": { "type": "git", "url": "https://github.com/eemeli/make-plural.js.git" }, | ||
"bugs": { "url": "https://github.com/eemeli/make-plural.js/issues" }, | ||
"files": [ "bin/", "data/", "make-plural.js" ], | ||
"bin": { "make-plural": "./bin/make-plural" }, | ||
"main": "make-plural" | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/eemeli/make-plural.js.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/eemeli/make-plural.js/issues" | ||
}, | ||
"files": [ | ||
"bin/", | ||
"data/", | ||
"make-plural.js" | ||
], | ||
"bin": { | ||
"make-plural": "./bin/make-plural" | ||
}, | ||
"main": "make-plural", | ||
"scripts": { | ||
"prepublish": "make", | ||
"test": "make test" | ||
}, | ||
"devDependencies": { | ||
"babel": "^4.7.9", | ||
"expect.js": "^0.3.1", | ||
"http-server": "^0.7.5", | ||
"mocha": "^2.2.1" | ||
} | ||
} |
138
README.md
make-plural | ||
=========== | ||
A JavaScript module that translates [Unicode CLDR](http://cldr.unicode.org/) | ||
[![ISC License](https://img.shields.io/npm/l/make-plural.svg)](http://en.wikipedia.org/wiki/ISC_license) | ||
[![Build Status](https://travis-ci.org/eemeli/make-plural.js.svg?branch=master)](https://travis-ci.org/eemeli/make-plural.js) | ||
Make-plural is a JavaScript module that translates [Unicode CLDR](http://cldr.unicode.org/) | ||
[pluralization rules](http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html) | ||
to JavaScript functions. | ||
Can be used as a CommonJS or AMD module, or directly in a browser environment. | ||
It's written in [ECMAScript 6](https://people.mozilla.org/~jorendorff/es6-draft.html) and transpiled using [Babel](https://babeljs.io/) to CommonJS, AMD and ES6 module formats, as well as being suitable for use in browser environments. | ||
@@ -18,5 +21,14 @@ | ||
``` | ||
bower install make-plural | ||
``` | ||
or | ||
``` | ||
git clone https://github.com/eemeli/make-plural.js.git | ||
cd make-plural.js | ||
npm install | ||
make all | ||
make test-browser | ||
``` | ||
## Usage: Node | ||
@@ -26,16 +38,19 @@ | ||
> MakePlural = require('make-plural') | ||
{ [Function] opt: {}, rules: {}, load: [Function] } | ||
{ [Function: MakePlural] | ||
cardinals: true, | ||
ordinals: false, | ||
rules: { data: {}, rootPath: './data/' } } | ||
> sk = MakePlural('sk') | ||
{ [Function] toString: [Function] } | ||
> sk = new MakePlural('sk') | ||
{ [Function] | ||
obj: | ||
{ lc: 'sk', | ||
cardinals: true, | ||
ordinals: false, | ||
parser: { v0: 1, i: 1 }, | ||
tests: { obj: [Circular], ordinal: {}, cardinal: [Object] }, | ||
fn: [Circular] }, | ||
test: [Function], | ||
toString: [Function] } | ||
> console.log(sk.toString()) | ||
function(n) { | ||
var s = String(n).split('.'), i = s[0], v0 = !s[1]; | ||
return (n == 1 && v0) ? 'one' | ||
: ((i >= 2 && i <= 4) && v0) ? 'few' | ||
: (!v0) ? 'many' | ||
: 'other'; | ||
} | ||
> sk(1) | ||
@@ -53,9 +68,33 @@ 'one' | ||
> en = MakePlural('en', {ordinals:1}) | ||
{ [Function] toString: [Function] } | ||
> console.log(sk.toString()) | ||
function(n) { | ||
var s = String(n).split('.'), i = s[0], v0 = !s[1]; | ||
return (i == 1 && v0 ) ? 'one' | ||
: ((i >= 2 && i <= 4) && v0 ) ? 'few' | ||
: (!v0 ) ? 'many' | ||
: 'other'; | ||
} | ||
> en = new MakePlural('en', {ordinals:1}) | ||
{ [Function] | ||
obj: | ||
{ lc: 'en', | ||
cardinals: true, | ||
ordinals: 1, | ||
parser: { n: 1, n10: 1, n100: 1, v0: 1 }, | ||
tests: { obj: [Circular], ordinal: [Object], cardinal: [Object] }, | ||
fn: [Circular] }, | ||
test: [Function], | ||
toString: [Function] } | ||
> en(2) | ||
'other' | ||
> en(2, true) | ||
'two' | ||
> console.log(en.toString()) | ||
function(n,ord) { | ||
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); | ||
n10 = t0 && s[0].slice(-1), n100 = t0 && s[0].slice(-2); | ||
if (ord) return (n10 == 1 && n100 != 11) ? 'one' | ||
@@ -67,10 +106,5 @@ : (n10 == 2 && n100 != 12) ? 'two' | ||
} | ||
``` | ||
> en(2) | ||
'other' | ||
> en(2, true) | ||
'two' | ||
``` | ||
## Usage: Web | ||
@@ -81,6 +115,6 @@ | ||
<script> | ||
var ru = MakePlural('ru', {ordinals:1}); | ||
console.log(ru.toString()); | ||
var ru = new MakePlural('ru', {ordinals:1}); | ||
console.log('1: ' + ru(1) + ', 3.0: ' + ru(3.0) + | ||
', "1.0": ' + ru('1.0') + ', "0": ' + ru('0')); | ||
console.log(ru.toString()); | ||
</script> | ||
@@ -90,5 +124,7 @@ ``` | ||
``` | ||
function(n,ord) { | ||
var s = String(n).split('.'), i = s[0], v0 = !s[1], i10 = i.substr(-1), | ||
i100 = i.substr(-2); | ||
1: one, 3.0: few, "1.0": other, "0": many | ||
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'; | ||
@@ -102,10 +138,8 @@ return (v0 && i10 == 1 && i100 != 11) ? 'one' | ||
} | ||
1: one, 3.0: few, "1.0": other, "0": many | ||
``` | ||
If `request()` isn't available, the CLDR rules are fetched automatically when | ||
If `require()` isn't available, the CLDR rules are fetched automatically when | ||
required using synchronous `XMLHttpRequest` calls for the JSON files at the | ||
default locations. If that doesn't work for you, you should call | ||
`MakePlural.load(cldr)` before calling `MakePlural()`. | ||
`MakePlural.load(cldr)` before calling `new MakePlural()`. | ||
@@ -129,3 +163,3 @@ | ||
$ ./bin/make-plural fr | ||
function fr(n,ord) { | ||
function fr(n, ord) { | ||
if (ord) return (n == 1) ? 'one' : 'other'; | ||
@@ -142,5 +176,5 @@ return (n >= 0 && n < 2) ? 'one' : 'other'; | ||
### MakePlural(lc, opt) | ||
Returns a function that takes a single argument `n` and returns its plural | ||
category for the given locale `lc`. | ||
### new MakePlural(lc, opt) | ||
Returns a function that takes an argument `n` and returns its plural category | ||
for the given locale `lc`. | ||
@@ -151,21 +185,15 @@ The returned function has an overloaded `toString(name)` method that may be | ||
The optional `opt` parameter may contain the following members, each of which is | ||
assumed false by default: | ||
* `no_cardinals` — if true, rules for cardinal values (1 day, 2 days, etc.) | ||
are not included | ||
* `no_tests` — if true, the generated function is not verified by testing it | ||
with each of the example values included in the CLDR rules | ||
The optional `opt` parameter may contain the following boolean members: | ||
* `cardinals` — if true, rules for cardinal values (1 day, 2 days, etc.) are | ||
included | ||
* `ordinals` — if true, rules for ordinal values (1st, 2nd, etc.) are included | ||
* `quiet` — if true, no output is reported to `console.error` on error | ||
If `opt.ordinals` is true and `opt.no_cardinals` is not true, the returned | ||
function takes a second parameter `ord`. Then, if `ord` is true, the function | ||
will return the ordinal rather than cardinal category applicable to `n` in | ||
locale `lc`. | ||
If both `opt.ordinals` and `opt.cardinals` are true, the returned function takes | ||
a second parameter `ord`. Then, if `ord` is true, the function will return the | ||
ordinal rather than cardinal category applicable to `n` in locale `lc`. | ||
If `opt` is not set, it takes the value of `MakePlural.opt`. If `lc` is not set, | ||
it takes the value of `opt.lc`. | ||
If `lc` or the `opt` values are not set, the values are taken from | ||
`MakePlural.lc` (no default value), `MakePlural.cardinals` (default `true`) and | ||
`MakePlural.ordinals` (default `false`). | ||
In a context where `module.exports` is not available but `exports` is, this | ||
function is exported as `MakePlural.get()`. | ||
@@ -190,3 +218,4 @@ ### MakePlural.load(cldr, ...) | ||
None. CLDR plural rule data is included in JSON format; make-plural supports the | ||
Make-plural has no runtime dependencies. CLDR plural rule data is included in | ||
JSON format; make-plural supports the | ||
[LDML Language Plural Rules](http://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules) | ||
@@ -204,4 +233,5 @@ as used in CLDR release 24 and later. | ||
); | ||
> MakePlural('ar')(3.14); | ||
> ar = new MakePlural('ar'); | ||
> ar(3.14); | ||
'other' | ||
``` |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
99854
1414
226
0
4
1