overleaf/services/web/scripts/translations/translateLocales.js

114 lines
3.2 KiB
JavaScript
Raw Normal View History

import yargs from 'yargs/yargs'
import { hideBin } from 'yargs/helpers'
import Path from 'path'
import fs from 'fs'
import { fileURLToPath } from 'url'
import Settings from '../../config/settings.defaults.js'
import Readline from 'readline'
import { loadLocale as loadTranslations } from './utils.js'
const __dirname = fileURLToPath(new URL('.', import.meta.url))
const LOCALES = Path.join(__dirname, '../../locales')
const VALID_LOCALES = Object.keys(Settings.translatedLanguages).filter(
locale => locale !== 'en'
)
const readline = Readline.createInterface({
input: process.stdin,
output: process.stdout,
})
const argv = yargs(hideBin(process.argv))
.usage('Translate locales')
.option('locale', {
alias: 'l',
type: 'string',
required: 'true',
description: 'Target 2-letter locale code',
choices: VALID_LOCALES,
})
.option('skip-until', {
type: 'string',
description: 'Skip locales until after the provided key',
})
.parse()
async function translateLocales() {
let { locale, skip } = argv
console.log(`Looking for missing [${locale}] translations...`)
const keysToUploadFolder = Path.join(__dirname, `translated-keys-to-upload`)
if (!fs.existsSync(keysToUploadFolder)) {
fs.mkdirSync(keysToUploadFolder)
}
const localeKeysToUploadPath = Path.join(keysToUploadFolder, `${locale}.json`)
const keysToUpload = fs.existsSync(localeKeysToUploadPath)
? JSON.parse(fs.readFileSync(localeKeysToUploadPath, 'utf-8'))
: []
const englishTranslations = await loadTranslations('en')
const englishKeys = Object.keys(englishTranslations)
const localeTranslations = await loadTranslations(locale)
const translatedKeys = Object.keys(localeTranslations)
console.log(
`Currently translated: ${translatedKeys.length} / ${englishKeys.length}`
)
for (const key of englishKeys) {
if (skip) {
if (key === skip) skip = ''
continue
}
const translation = localeTranslations[key]
if (!translation || translation.length === 0) {
let value = await prompt(
`\nMissing translation for: ${key}\n"${englishTranslations[key]}"\n`
)
while (value.includes("'")) {
value = await prompt(
`\nTranslations should not contain single-quote characters, please use curvy quotes ( or ) instead:\n`
)
}
if (!value) {
console.log(`Skipping ${key}`)
continue
}
localeTranslations[key] = value
const path = Path.join(LOCALES, `${locale}.json`)
const sorted =
JSON.stringify(
localeTranslations,
Object.keys(localeTranslations).sort(),
2
) + '\n'
fs.writeFileSync(path, sorted)
keysToUpload.push(key)
const formattedKeysToUpload =
JSON.stringify(Array.from(new Set(keysToUpload)), null, 2) + '\n'
fs.writeFileSync(localeKeysToUploadPath, formattedKeysToUpload)
console.log(`"${key}": "${value}" added to ${locale}.json`)
}
}
}
function prompt(text) {
return new Promise((resolve, reject) =>
readline.question(text, value => {
resolve(value)
})
)
}
try {
await translateLocales()
process.exit(0)
} catch (error) {
console.error(error)
process.exit(1)
}