-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathplural-forms.js
49 lines (44 loc) · 1.69 KB
/
plural-forms.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/*
Examples from https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html
Note: true == 1, false == 0
Plural-Forms: nplurals=1; plural=0;
Plural-Forms: nplurals=2; plural=n != 1;
Plural-Forms: nplurals=2; plural=n>1;
Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1;
Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;
Plural-Forms: nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;
Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2;
Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2;
Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;
Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5;
*/
const validPlural = (plural) => {
const words = plural.match(/\b\w+\b/g)
if (!words) return null
for (let i = 0; i < words.length; ++i) {
const word = words[i]
if (word !== 'n' && isNaN(Number(word))) return null
}
return plural.trim()
}
const getPluralFunction = (pluralForms) => {
if (!pluralForms) return null
let nplurals
let plural
pluralForms.split(';').forEach(part => {
const m = part.match(/^\s*(\w+)\s*=(.*)/)
switch (m && m[1]) {
case 'nplurals':
nplurals = Number(m[2])
break
case 'plural':
plural = validPlural(m[2])
break
}
})
if (!nplurals || !plural) throw new Error('Invalid plural-forms: ' + pluralForms)
const pluralFunc = new Function('n', `return 'p' + Number(${plural})`)
pluralFunc.cardinal = new Array(nplurals).fill().map((_, i) => 'p' + i)
return pluralFunc
}
module.exports = getPluralFunction