peertube-plugin-livechat/build-languages.js
John Livingston 89a11cd3d6
Changing the way the translations are handled:
To make the Weblate integration simplier, this commit merge all
translations in yml files (there is no more distinction between
standards and settings strings)

This yml files will be handled by Weblate.

TODO: document the new translation process.
2023-06-09 17:08:39 +02:00

143 lines
4.2 KiB
JavaScript

/**
* 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(/^.*\/(\w+)\.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)
}
}
async writeJSONTranslations () {
console.log('Writing JSON files...')
for (const l of this.langs) {
const filePath = path.resolve(this.destinationDir, l + '.json')
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
})