-
Notifications
You must be signed in to change notification settings - Fork 4
/
index.js
94 lines (90 loc) · 2.59 KB
/
index.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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
const { mo, po } = require('gettext-parser')
const getPluralFunction = require('./plural-forms')
const defaultOptions = {
defaultCharset: null,
forceContext: false,
pluralFunction: null,
pluralVariablePattern: /%(?:\((\w+)\))?\w/,
replacements: [
{
pattern: /[\\{}#]/g,
replacement: '\\$&'
},
{
pattern: /%(\d+)(?:\$\w)?/g,
replacement: (_, n) => `{${n - 1}}`
},
{
pattern: /%\((\w+)\)\w/g,
replacement: '{$1}'
},
{
pattern: /%\w/g,
replacement: function () { return `{${this.n++}}` },
state: { n: 0 }
},
{
pattern: /%%/g,
replacement: '%'
}
],
verbose: false
}
const getMessageFormat = (
{ pluralFunction, pluralVariablePattern, replacements, verbose },
{ msgid, msgid_plural, msgstr }
) => {
if (!msgid || !msgstr) return null
if (!msgstr[0]) {
if (verbose) console.warn('Translation not found:', msgid)
msgstr[0] = msgid
}
if (msgid_plural) {
if (!pluralFunction) throw new Error('Plural-Forms not defined')
for (let i = 1; i < pluralFunction.cardinal.length; ++i) {
if (!msgstr[i]) {
if (verbose) console.warn('Plural translation not found:', msgid, i)
msgstr[i] = msgid_plural
}
}
}
msgstr = msgstr.map(str => (
replacements.reduce((str, { pattern, replacement, state }) => {
if (state) replacement = replacement.bind(Object.assign({}, state))
return str.replace(pattern, replacement)
}, str)
))
if (msgid_plural) {
const m = msgid_plural.match(pluralVariablePattern)
const pv = m && m[1] || '0'
const pc = pluralFunction.cardinal.map((c, i) => `${c}{${msgstr[i]}}`)
return `{${pv}, plural, ${pc.join(' ')}}`
}
return msgstr[0]
}
const convert = (parse, input, options) => {
options = Object.assign({}, defaultOptions, options)
const { headers, translations } = parse(input, options.defaultCharset)
if (!options.pluralFunction) {
options.pluralFunction = getPluralFunction(headers['Plural-Forms'])
}
let hasContext = false
for (const context in translations) {
if (context) hasContext = true
const data = translations[context]
for (const id in data) {
const mf = getMessageFormat(options, data[id])
if (mf) data[id] = mf
else delete data[id]
}
}
return {
headers,
pluralFunction: options.pluralFunction,
translations: hasContext || options.forceContext ? translations : translations['']
}
}
module.exports = {
parseMo: (input, options) => convert(mo.parse, input, options),
parsePo: (input, options) => convert(po.parse, input, options)
}