This repository has been archived by the owner on Mar 4, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
100 lines (92 loc) · 3.35 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
95
96
97
98
99
100
const common = require('common-prefix')
const YAML = require('yaml').default
const pluralCategories = require('make-plural/umd/pluralCategories')
const cldrPluralCategories = ['zero', 'one', 'two', 'few', 'many', 'other']
const defaultOptions = {
defaultLocale: 'en',
includeLocales: null,
pluralVariable: 'count',
replacements: [
{ pattern: /[%#]{(\w+)}/g, replacement: '\x02$1\x03' },
{ pattern: /[\\{}#]/g, replacement: '\\$&' },
{ pattern: /\x02/g, replacement: '{' },
{ pattern: /\x03/g, replacement: '}' }
],
schema: 'failsafe',
verbose: false
}
const getMessageFormat = (msg, { replacements }) => msg ? (
replacements.reduce((msg, { pattern, replacement, state }) => {
if (state) replacement = replacement.bind(Object.assign({}, state))
return msg.replace(pattern, replacement)
}, String(msg))
) : ''
const isPluralObject = (data, locale, { verbose }) => {
const { cardinal: pluralKeys } = pluralCategories[locale] || {}
const keys = Object.keys(data)
if (!pluralKeys || pluralKeys.length === 0 || keys.length === 0) return false
if (
keys.length === pluralKeys.length &&
keys.every(key => (
pluralKeys.includes(key) &&
(!data[key] || typeof data[key] !== 'object')
))
) return true
if (verbose && keys.every(key => cldrPluralCategories.includes(key))) {
console.warn(`yaml-to-messageformat: Nearly valid plural for locale ${locale}: ${JSON.stringify(data)}`)
}
return false
}
const getPluralMessage = (data, options) => {
const keys = Object.keys(data)
const messages = keys.map(key => getMessageFormat(data[key], options))
const prefix = common(messages)
const suffixLength = common(messages.map(msg => msg.split('').reverse().join(''))).length
const suffix = suffixLength > 0 ? messages[0].slice(-suffixLength) : ''
const cut = suffixLength > 0 ? (
(msg) => msg.slice(prefix.length, -suffixLength)
) : prefix ? (
(msg) => msg.slice(prefix.length)
) : (
(msg) => msg
)
const pc = keys.map((key, i) => `${key}{${cut(messages[i])}}`)
const pv = options.pluralVariable
return `${prefix}{${pv}, plural, ${pc.join(' ')}}${suffix}`
}
const convertData = (data, locale, options) => {
if (!data) {
return ''
} else if (Array.isArray(data)) {
return data.map(d => convertData(d, locale, options))
} else if (typeof data === 'object') {
if (options.pluralVariable && isPluralObject(data, locale, options)) {
return getPluralMessage(data, options)
} else {
return Object.keys(data).reduce((res, key) => {
const { includeLocales: il, verbose } = options
const isLcKey = (!il || il.includes(key)) && pluralCategories[key]
if (isLcKey) {
options._lc[key] = true
if (verbose) console.log(`yaml-to-messageformat: Found locale ${key}`)
}
res[key] = convertData(data[key], isLcKey ? key : locale, options)
return res
}, {})
}
} else {
return getMessageFormat(data, options)
}
}
const convert = (input, options) => {
options = Object.assign({}, defaultOptions, options)
options._lc = { [options.defaultLocale]: true }
let data = YAML.parse(input, options)
if (data.length === 1) data = data[0]
const translations = convertData(data, options.defaultLocale, options)
return {
locales: Object.keys(options._lc).filter(lc => lc),
translations
}
}
module.exports = convert