-
Notifications
You must be signed in to change notification settings - Fork 149
/
build.js
105 lines (97 loc) · 3.68 KB
/
build.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
101
102
103
104
105
import loc from './loc/loc.js'
// First, collect all types of languages present, so we do not have to maintain a list
// This enables us to arbitrarily add translations to strings
// For any new language type detected, a new translated output file is generated
// For any strings that lack translations for a lang type, we can fall back to another language
const findLang = (obj, types)=>{
// iterates object props recursively
Object.entries(obj).forEach( ([langType, string]) => {
if(langType == '$$') return
// check whether value is object or string
if(typeof string === 'object') {
// if object, iterate recursively
findLang(string, types)
} else {
// if string, add to language set
if(!types.has(langType)) {
types.set(langType, {})
}
}
})
return types
}
console.log('Detecting loc types...')
const languages = findLang(loc, new Map())
// add debugging languages and replacers
languages.set('_db1', {})
languages.set('_db2', {})
const debugReplace = {
_db1: () => '🍎',
_db2: (key) => `{${key}}`}
console.log(` Found ${languages.size} languages`)
// next, compile each language type to its own file
// we search for strings present for the lang type, if not found, we fall back to english
// if not even english is present (should never be the case), we fall back to whatever is present
const compile = (obj, lang, currentType, metrics, tree)=>{
// iterate object props recursively
Object.entries(obj).forEach( ([key, value]) => {
if(key == '$$') return
const ref = `${tree?tree+'.':''}${key}`
// check whether value is object or string
if(typeof value === 'object') {
// if object, check whether object has strings as children
if(Object.entries(value).some(v => typeof v[1] === 'string')) {
// check whether a string of our language is present
if(value[currentType] !== undefined) {
// i guess they never miss huh
metrics.hit++
lang[key] = debugReplace[currentType] ?
debugReplace[currentType](ref) : value[currentType]
} else {
// if we have no translation, fall back to value
// fall back order: $$, en, any other
const fallback = value['$$'] || value['en'] || value[Object.keys(value)[0]]
if(!fallback) throw 'Error: emtpy translation:' + key
// if it is not an untranslated, it is a missing translation
if(value['$$'] === undefined) metrics.miss++
lang[key] = debugReplace[currentType] ?
debugReplace[currentType](ref) : fallback
}
} else {
// no strings as children, meaning we should iterate deeper
compile(value, lang[key] = (value.length ? [] : {}),
currentType, metrics, ref)
}
}
})
}
// iterate languages and compile
console.log('Compiling...')
const results = []
languages.forEach((lang, type) => {
const metrics = {hit: 0, miss: 0}
compile(loc, lang, type, metrics)
const amount = `${String(metrics.hit).padStart(3, ' ')}/${metrics.hit+metrics.miss}`
const percentage = ((metrics.hit/(metrics.hit+metrics.miss))*100) >> 0
if(!type.includes('_'))
results.push({
type,
count : metrics.hit,
string: ` ${type} → ${amount} ${String(percentage).padStart(3, ' ')}%`})
})
// sort, print
results.sort( (a, b) => b.count - a.count )
results.forEach( r => console.log(r.string))
// store as files
console.log('Exporting JSON files...')
const fs = require('fs')
const path = process.argv[2] || './dist/loc/'
if (!fs.existsSync(path)) {
fs.mkdirSync(path)
}
languages.forEach(async (lang, type)=>{
await fs.writeFile(path+`${type}.json`, JSON.stringify(lang), (e)=>{
if(e) throw e
})
})
console.log(' done.')