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.2.0 to 1.3.0

data/unicode-cldr-ordinal-rules.json

109

make-plural.js

@@ -89,16 +89,26 @@ /**

function test(fn, tests, opt) {
function test(lc, fn, tests, opt) {
var ok = true,
_e = function(t) {
ok = false;
if (!opt['quiet']) console.error(
'ERROR: plural rule self-test failed for v = '
+ (typeof t == 'string' ? '"' + t + '"' : t)
+ ' (was "' + fn(t) + '", expected "' + k + '")');
_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 k in tests) {
tests[k].forEach(function(v) {
if (fn(v) != k) _e(v);
else if (!/\.0+$/.test(v) && fn(Number(v)) != k) _e(Number(v));
});
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);
});
}
}

@@ -112,3 +122,3 @@ return ok;

var _require = (typeof require == 'function') ? require : function(url) {
if (!cldr && Plurals.src_url) url = Plurals.src_url.replace(/[^\/]*$/, url);
if (Plurals.src_url && (url[0] == '.')) url = Plurals.src_url.replace(/[^\/]*$/, url);
var xhr = new XMLHttpRequest();

@@ -119,25 +129,64 @@ xhr.open('get', url, false);

};
if (!cldr) cldr = _require('./data/unicode-cldr-plural-rules.json');
else if (typeof cldr == 'string') cldr = _require(cldr);
Plurals.rules = cldr && cldr['supplemental']['plurals-type-cardinal'];
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'];
}
}
};
Plurals.build = function(lc, opt) {
var fn, fn_str, lines = [], symbols = {}, tests = {};
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 (!Plurals.rules) Plurals.set_rules();
if (!Plurals.rules[lc]) { if (!opt['quiet']) console.error('ERROR: locale "' + lc + '" not found'); return null; }
for (var r in Plurals.rules[lc]) {
var key = r.replace('pluralRule-count-', ''),
parts = Plurals.rules[lc][r].split(/@\w*/),
cond = parts.shift().trim();
if (cond) lines.push('if (' + parse(cond, symbols) + ') return \'' + key + '\';');
tests[key] = test_values(parts.join(' '));
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) + ';'));
}
}
lines.unshift(vars(symbols));
lines.push('return \'other\';');
fn = new Function('n', lines.join('\n').trim());
if (!opt['no_tests'] && !test(fn, tests, opt)) return null;
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 = 'function(n) {\n ' + lines.join('\n ').trim() + '\n}';
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 ');

@@ -144,0 +193,0 @@ return fn_str;

{
"name": "make-plural",
"version": "1.2.0",
"version": "1.3.0",
"description": "Translates Unicode CLDR pluralization rules to executable JavaScript",

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

@@ -25,18 +25,12 @@ make-plural

> console.log( Plurals.build('fr') )
function(n) {
if (n >= 0 && n < 2) return 'one';
return 'other';
}
> console.log( Plurals.build('sk') )
function(n) {
> console.log(Plurals.build('sk')) // Slovak
function(n,ord) {
var s = String(n).split('.'), i = s[0], v0 = !s[1];
if (n == 1 && v0) return 'one';
if ((i >= 2 && i <= 4) && v0) return 'few';
if (!v0) return 'many';
return 'other';
return (n == 1 && v0) ? 'one'
: ((i >= 2 && i <= 4) && v0) ? 'few'
: (!v0) ? 'many'
: 'other';
}
> sk = Plurals.build('sk', {'return_function':1})
> sk = Plurals.build('sk', { 'return_function':1 })
[Function]

@@ -55,2 +49,22 @@

'other'
> console.log(Plurals.build('en', { 'ordinals':1 })) // English
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';
}
> en = Plurals.build('en', { 'ordinals':1, 'return_function':1 })
[Function]
> en(2)
'other'
> en(2, true)
'two'
```

@@ -63,6 +77,6 @@

<script>
console.log( Plurals.build('sk') );
var sk = Plurals.build('sk', {'return_function':1});
console.log( '1: ' + sk(1) + ', 3.0: ' + sk(3.0) +
', "1.0": ' + sk('1.0') + ', "0": ' + sk('0') );
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'));
</script>

@@ -72,8 +86,9 @@ ```

```
function(n) {
function(n,ord) {
var s = String(n).split('.'), i = s[0], v0 = !s[1];
if (n == 1 && v0) return 'one';
if ((i >= 2 && i <= 4) && v0) return 'few';
if (!v0) return 'many';
return 'other';
if (ord) return 'other';
return (n == 1 && v0) ? 'one'
: ((i >= 2 && i <= 4) && v0) ? 'few'
: (!v0) ? 'many'
: 'other';
}

@@ -84,8 +99,34 @@

If `request()` isn't available, the CLDR rules are fetched automatically by the
first call to `Plurals.build()` using a synchronous `XMLHttpRequest` for the
JSON file at the location `data/unicode-cldr-plural-rules.json` relative to the
given `path/to/make-plural.js`. If that doesn't work for you, you should call
If `request()` 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
`Plurals.set_rules(cldr)` before calling `Plurals.build()`.
## Usage: CLI
```sh
$ ./bin/make-plural
Locales verified ok:
af ak am ar asa ast az be bem bez bg bh bm bn bo br brx bs ca cgg chr ckb
cs cy da de dsb dv dz ee el en eo es et eu fa ff fi fil fo fr fur fy ga
gd gl gsw gu guw gv ha haw he hi hr hsb hu hy id ig ii in is it iu iw ja
jbo jgo ji jmc jv jw ka kab kaj kcg kde kea kk kkj kl km kn ko ks ksb ksh
ku kw ky lag lb lg lkt ln lo lt lv mas mg mgo mk ml mn mo mr ms mt my nah
naq nb nd ne nl nn nnh no nqo nr nso ny nyn om or os pa pap pl prg ps pt
pt-PT rm ro rof root ru rwk sah saq se seh ses sg sh shi si sk sl sma smi
smj smn sms sn so sq sr ss ssy st sv sw syr ta te teo th ti tig tk tl tn
to tr ts tzm ug uk ur uz ve vi vo vun wa wae wo xh xog yi yo zh zu
$ ./bin/make-plural fr
function(n,ord) {
if (ord) return (n == 1) ? 'one' : 'other';
return (n >= 0 && n < 2) ? 'one' : 'other';
}
$ ./bin/make-plural fr 1.5
one
```
## Methods

@@ -95,8 +136,12 @@

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`. The
optional `opt` object may contain the following members, each of which is
assumed as false by default:
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
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.)
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
* `ordinals` — if true, rules for ordinal values (1st, 2nd, etc.) are included
* `quiet` — if true, no output is reported to `console.error` on error

@@ -106,7 +151,10 @@ * `return_function` — if true, `build` returns an executable function of `n`

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`.
### 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/25/supplemental/plurals.json).
By default, the included rules in `data/unicode-cldr-plural-rules.json` are
used.
file formatted like [this](http://www.unicode.org/repos/cldr-aux/json/26/supplemental/plurals.json).

@@ -117,2 +165,5 @@ If called within a context where `request()` isn't available and `cldr` is a

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

@@ -119,0 +170,0 @@ ## Dependencies

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