peertube-plugin-livechat/build-languages.js

155 lines
4.8 KiB
JavaScript
Raw Permalink Normal View History

2024-05-23 09:42:14 +00:00
// 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]
})
2023-02-16 05:58:28 +00:00
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)) {
2023-07-14 11:39:34 +00:00
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
})