-
-
Notifications
You must be signed in to change notification settings - Fork 26
/
build-languages.js
154 lines (135 loc) · 4.84 KB
/
build-languages.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/>
//
// SPDX-License-Identifier: AGPL-3.0-only
/**
* This script is used to build the translations files.
*
* Indeed, some strings used in plugin settings are not easy to write
* in JSON format (contains html, double quotes, line breaks, ...).
* So we use YAML files to translates these strings,
* including the english version.
*
* This scripts takes the standard JSON files, the YAML translation files,
* and mixes everything up in dist/languages/xx.json.
*/
const fs = require('fs')
const path = require('path')
const YAML = require('yaml')
class BuildLanguages {
destinationDir = null
langs = []
translationsStrings = {}
monoLingualReferences = null
constructor () {
this.destinationDir = path.resolve(__dirname, 'dist', 'languages')
}
async generateFiles () {
await this.loadLangs()
await this.initTranslationStrings()
await this.readYamlTranslations()
await this.ensureDestinationDir()
await this.writeJSONTranslations()
await this.writeMonoLingualReferences()
}
loadLangs () {
const packagejson = require('./package.json')
const translations = packagejson.translations || {}
this.langs = Object.values(translations).map(filename => {
return filename.match(/^.*\/([a-zA-Z-]+)\.json$/)[1]
})
console.log('Existing languages: ', this.langs)
}
initTranslationStrings () {
console.log('Initializing translations strings...')
const translationsStrings = {}
for (const l of this.langs) {
translationsStrings[l] = {}
}
this.translationsStrings = translationsStrings
}
async readYamlTranslations () {
console.log('Reading Yaml translation strings...')
// First we must get the english reference file,
// that will give us the keys to use in final JSON.
const reference = await this.getYmlFileContent(path.resolve(__dirname, 'languages', 'en.yml'))
this.monoLingualReferences = reference
const translationsStrings = this.translationsStrings
for (const l of this.langs) {
if (l === 'en') {
console.log('Skipping english, because it is the reference language.')
continue
}
const filePath = path.resolve(__dirname, 'languages', l + '.yml')
const o = await this.getYmlFileContent(filePath)
for (const k in o) {
if (!(k in reference)) {
throw new Error(`File ${filePath} contains unknown keys. Key=${k}.`)
}
if ((typeof o[k]) !== 'string') {
// ignoring untranslated strings.
continue
}
const newKey = reference[k]
this.translationsStrings[l][newKey] = o[k]
}
}
}
async getYmlFileContent (filePath) {
if (!fs.existsSync(filePath)) {
console.warn(`File ${filePath} missing, ignoring.`)
return {}
}
const content = await fs.promises.readFile(filePath, 'utf8')
const o = YAML.parse(content) || {}
for (const k in o) {
let v = o[k]
if (v === null) {
// this value is ok!
continue
}
if ((typeof v) !== 'string') {
throw new Error(`File ${filePath} contains strings that are not strings! Key=${k}`)
}
// We are normalizing the string, to avoid problems.
// As it is supposed to be html, we will strip newlines and multiple adjacent spaces.
v = v.replace(/\n/g, ' ')
v = v.replace(/\s\s+/g, ' ')
v = v.trim()
o[k] = v
}
return o
}
async ensureDestinationDir () {
if (!fs.existsSync(this.destinationDir)) {
await fs.promises.mkdir(this.destinationDir, { recursive: true })
}
}
async writeJSONTranslations () {
console.log('Writing JSON files...')
for (const l of this.langs) {
const filePath = path.resolve(this.destinationDir, l + '.json')
// Waiting for this to be implemented:
// https://github.com/Chocobozzz/PeerTube/issues/5904
// (also see https://github.com/JohnXLivingston/peertube-plugin-livechat/issues/224)
// we are adding a special entry with the language key, so we can use frontend
// translation function to get the path for localized documentation.
// See frontend getLangCode and localizedHelpUrl functions.
const content = this.translationsStrings[l]
content['_language'] = l
await fs.promises.writeFile(filePath, JSON.stringify(this.translationsStrings[l]))
}
}
async writeMonoLingualReferences () {
console.log('Writing JSON reference files...')
if (!this.monoLingualReferences) {
throw new Error('Missing monolingual reference content!')
}
const filePath = path.resolve(this.destinationDir, 'en.reference.json')
await fs.promises.writeFile(filePath, JSON.stringify(this.monoLingualReferences))
}
}
const bl = new BuildLanguages()
bl.generateFiles().then(() => {}, (err) => {
console.error(err)
throw err
})