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

make-plural

Package Overview
Dependencies
Maintainers
1
Versions
45
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

make-plural - npm Package Compare versions

Comparing version 1.3.0 to 2.0.0

175

make-plural.js

@@ -62,10 +62,2 @@ /**

function test_values(str) {
return str
.replace(/decimal|integer/g, '')
.replace(/^[ ,]+|[ ,…]+$/g, '')
.replace(/(0\.[0-9])~(1\.[1-9])/g, '$1 1.0 $2')
.split(/[ ,~…]+/);
}
function vars(symbols) {

@@ -90,2 +82,51 @@ var vars = [];

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 : ');
};
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');
}
function test(lc, fn, tests, opt) {

@@ -119,89 +160,57 @@ var ok = true,

var Plurals = {};
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);
}
Plurals.set_rules = function(cldr) {
var _require = (typeof require == 'function') ? require : function(url) {
if (Plurals.src_url && (url[0] == '.')) url = Plurals.src_url.replace(/[^\/]*$/, url);
var xhr = new XMLHttpRequest();
xhr.open('get', url, false);
xhr.send();
return (xhr.status == 200) && JSON.parse(xhr.responseText);
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');
};
if (typeof cldr == 'string') cldr = _require(cldr);
if (cldr && cldr['supplemental']) {
if (!Plurals.rules) Plurals.rules = {};
if ('plurals-type-cardinal' in cldr['supplemental']) {
Plurals.rules['cardinal'] = cldr['supplemental']['plurals-type-cardinal'];
}
if ('plurals-type-ordinal' in cldr['supplemental']) {
Plurals.rules['ordinal'] = cldr['supplemental']['plurals-type-ordinal'];
}
}
return fn_body && (opt['no_tests'] || test(lc, fn, tests, opt)) ? fn : null;
};
Plurals.build = function(lc, opt) {
var fn, fn_str, fn_vars, lines = [], symbols = {},
tests = { 'ordinal':{}, 'cardinal':{} },
_compile = function(type, indent, req) {
var cases = [];
if (!Plurals.rules || !Plurals.rules[type]) {
Plurals.set_rules((type == 'ordinal')
? './data/unicode-cldr-ordinal-rules.json'
: './data/unicode-cldr-plural-rules.json');
}
if (Plurals.rules[type][lc]) {
for (var r in Plurals.rules[type][lc]) {
var key = r.replace('pluralRule-count-', ''),
parts = Plurals.rules[type][lc][r].split(/@\w*/),
cond = parts.shift().trim();
if (cond) cases.push([parse(cond, symbols), key]);
tests[type][key] = test_values(parts.join(' '));
}
} 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 : ');
}, _fold = function(l) {
return l.replace(/(.{1,72})( \|\| |$) ?/gm, '$1\n $2').replace(/\s+$/gm, '');
};
if (!opt) opt = {};
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) + ';'));
}
MakePlural.opt = {};
MakePlural.rules = {};
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;
});
}
if (!opt['no_cardinals']) {
var l = _compile('cardinal', ' ', true);
if (!l) return null;
lines.push(_fold(' return ' + l + ';'));
}
fn_vars = vars(symbols).replace(/(.{1,78})(,|$) ?/g, '\n $1$2').trim();
if (fn_vars) lines.unshift(' ' + fn_vars);
fn = new Function('n', 'ord', lines.join('\n').trim());
if (!opt['no_tests'] && !test(lc, fn, tests, opt)) return null;
if (opt['return_function']) return fn;
fn_str = (opt['ordinals'] && !opt['no_cardinals'] ? 'function(n,ord)' : 'function(n)')
+ ' {\n' + lines.join('\n').replace(/{\s*(return [^;]+;)\s*}/, '$1') + '\n}';
if (opt['minify']) fn_str = fn_str.replace(/\s+/g, '').replace(/{var/, '{var ');
return fn_str;
return MakePlural;
};
if ((typeof module !== 'undefined') && module.exports) {
module.exports = Plurals;
module.exports = MakePlural;
} else if (typeof exports !== 'undefined') {
// won't expose Plurals.rules
for (var p in Plurals) exports[p] = Plurals[p];
for (var p in MakePlural) exports[p] = MakePlural[p];
exports.get = MakePlural;
} else {
try { Plurals.src_url = Array.prototype.slice.call(document.getElementsByTagName('script')).pop().src; }
catch (e) { Plurals.src_url = ''; }
global.Plurals = Plurals;
try { MakePlural.src_url = Array.prototype.slice.call(document.getElementsByTagName('script')).pop().src; }
catch (e) { MakePlural.src_url = ''; }
global.MakePlural = MakePlural;
}
})(this);
{
"name": "make-plural",
"version": "1.3.0",
"version": "2.0.0",
"description": "Translates Unicode CLDR pluralization rules to executable JavaScript",

@@ -5,0 +5,0 @@ "keywords": ["unicode", "cldr", "i18n", "internationalization", "pluralization"],

@@ -6,3 +6,3 @@ make-plural

[pluralization rules](http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html)
to executable JavaScript functions.
to JavaScript functions.

@@ -12,7 +12,7 @@

```sh
```
npm install make-plural
```
or
```sh
```
git clone https://github.com/eemeli/make-plural.js.git

@@ -24,7 +24,7 @@ ```

```js
> Plurals = require('make-plural')
{ set_rules: [Function], build: [Function] }
> MakePlural = require('make-plural')
{ [Function] opt: {}, rules: {}, load: [Function] }
> console.log(Plurals.build('sk')) // Slovak
function(n,ord) {
> console.log(MakePlural('sk').toString())
function(n) {
var s = String(n).split('.'), i = s[0], v0 = !s[1];

@@ -37,4 +37,4 @@ return (n == 1 && v0) ? 'one'

> sk = Plurals.build('sk', { 'return_function':1 })
[Function]
> sk = MakePlural('sk')
{ [Function] toString: [Function] }

@@ -53,3 +53,3 @@ > sk(1)

> console.log(Plurals.build('en', { 'ordinals':1 })) // English
> console.log(MakePlural('en', {'ordinals':1}).toString())
function(n,ord) {

@@ -65,4 +65,4 @@ var s = String(n).split('.'), v0 = !s[1], t0 = Number(s[0]) == n,

> en = Plurals.build('en', { 'ordinals':1, 'return_function':1 })
[Function]
> en = MakePlural('en', {'ordinals':1})
{ [Function] toString: [Function] }

@@ -81,6 +81,6 @@ > en(2)

<script>
console.log(Plurals.build('sk', {'ordinals':1}));
var sk = Plurals.build('sk', { 'ordinals':1, 'return_function':1 });
console.log('1: ' + sk(1) + ', 3.0: ' + sk(3.0) +
', "1.0": ' + sk('1.0') + ', "0": ' + sk('0'));
console.log(MakePlural('ru', {'ordinals':1}).toString());
var ru = MakePlural('ru', {'ordinals':1});
console.log('1: ' + ru(1) + ', 3.0: ' + ru(3.0) +
', "1.0": ' + ru('1.0') + ', "0": ' + ru('0'));
</script>

@@ -91,11 +91,14 @@ ```

function(n,ord) {
var s = String(n).split('.'), i = s[0], v0 = !s[1];
var s = String(n).split('.'), i = s[0], v0 = !s[1], i10 = i.substr(-1),
i100 = i.substr(-2);
if (ord) return 'other';
return (n == 1 && v0) ? 'one'
: ((i >= 2 && i <= 4) && v0) ? 'few'
: (!v0) ? 'many'
return (v0 && i10 == 1 && i100 != 11) ? 'one'
: (v0 && (i10 >= 2 && i10 <= 4) && (i100 < 12
|| i100 > 14)) ? 'few'
: (v0 && i10 == 0 || v0 && (i10 >= 5 && i10 <= 9)
|| v0 && (i100 >= 11 && i100 <= 14)) ? 'many'
: 'other';
}
1: one, 3.0: few, "1.0": many, "0": other
1: one, 3.0: few, "1.0": other, "0": many
```

@@ -106,3 +109,3 @@

default locations. If that doesn't work for you, you should call
`Plurals.set_rules(cldr)` before calling `Plurals.build()`.
`MakePlural.load(cldr)` before calling `MakePlural()`.

@@ -126,3 +129,3 @@

$ ./bin/make-plural fr
function(n,ord) {
function fr(n,ord) {
if (ord) return (n == 1) ? 'one' : 'other';

@@ -139,9 +142,12 @@ return (n >= 0 && n < 2) ? 'one' : 'other';

### build(lc, opt)
By default, returns a string representation of a function that takes a single
argument `n` and returns its plural category for the given locale `lc`.
### MakePlural(lc, opt)
Returns a function that takes a single argument `n` and returns its plural
category for the given locale `lc`.
The optional `opt` object may contain the following members, each of which is
The returned function has an overloaded `toString(name)` method that may be
used to generate a clean string representation of the function, with an
optional name `name`.
The optional `opt` parameter may contain the following members, each of which is
assumed false by default:
* `minify` — if true, the string output of `build` is minified
* `no_cardinals` — if true, rules for cardinal values (1 day, 2 days, etc.)

@@ -153,6 +159,4 @@ are not included

* `quiet` — if true, no output is reported to `console.error` on error
* `return_function` — if true, `build` returns an executable function of `n`
rather than a string
if `opt.ordinals` is true and `opt.no_cardinals` is not true, the returned
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

@@ -162,6 +166,15 @@ will return the ordinal rather than cardinal category applicable to `n` in

### set_rules(cldr)
Sets the used CLDR rules to `cldr`, which may be an object or the path to a JSON
file formatted like [this](http://www.unicode.org/repos/cldr-aux/json/26/supplemental/plurals.json).
If `opt` is not set, it takes the value of `MakePlural.opt`. If `lc` is not set,
it takes the value of `opt.lc`.
In a context where `module.exports` is not available but `exports` is, this
function is exported as `MakePlural.get()`.
### MakePlural.load(cldr, ...)
Loads CLDR rules from one or more `cldr` variables, each of which may be an
object or the path to a JSON file formatted like
[this](http://www.unicode.org/repos/cldr-aux/json/26/supplemental/plurals.json).
The stored rules are kept in `MakePlural.rules.cardinal` and
`MakePlural.rules.ordinal`, which may also be directly accessed.
If called within a context where `request()` isn't available and `cldr` is a

@@ -171,6 +184,7 @@ string, it's taken as the URL of the JSON file that'll be fetched and parsed

By default, `build()` will call `set_rules(cldr)` when required, using the
rules included in `data/`: `unicode-cldr-plural-rules.json` and
By default, `MakePlural()` will call `MakePlural.load(cldr)` when required,
using the rules included in `data/`, `unicode-cldr-plural-rules.json` and
`unicode-cldr-ordinal-rules.json`.
## Dependencies

@@ -181,1 +195,14 @@

as used in CLDR release 24 and later.
Using `MakePlural.load()`, you may make use of external sources of CLDR data.
For example, the following works when using together with
[cldr-data](https://www.npmjs.org/package/cldr-data):
```js
> cldr = require('cldr-data');
> MakePlural = require('make-plural').load(
cldr('supplemental/plurals'),
cldr('supplemental/ordinals')
);
> MakePlural('ar')(3.14);
'other'
```

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