2024-10-24 08:18:37 -04:00
|
|
|
|
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'
|
2023-06-01 08:26:15 -04:00
|
|
|
|
|
2024-10-24 08:18:37 -04:00
|
|
|
|
const __dirname = fileURLToPath(new URL('.', import.meta.url))
|
2023-06-01 08:26:15 -04:00
|
|
|
|
const LOCALES = Path.join(__dirname, '../../locales')
|
2024-10-24 08:18:37 -04:00
|
|
|
|
const VALID_LOCALES = Object.keys(Settings.translatedLanguages).filter(
|
|
|
|
|
locale => locale !== 'en'
|
|
|
|
|
)
|
2023-06-01 08:26:15 -04:00
|
|
|
|
|
2024-10-24 08:18:37 -04:00
|
|
|
|
const readline = Readline.createInterface({
|
2023-06-01 08:26:15 -04:00
|
|
|
|
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,
|
|
|
|
|
})
|
2023-07-17 08:15:05 -04:00
|
|
|
|
.option('skip-until', {
|
|
|
|
|
type: 'string',
|
|
|
|
|
description: 'Skip locales until after the provided key',
|
|
|
|
|
})
|
2023-06-01 08:26:15 -04:00
|
|
|
|
.parse()
|
|
|
|
|
|
|
|
|
|
async function translateLocales() {
|
2023-07-17 08:15:05 -04:00
|
|
|
|
let { locale, skip } = argv
|
2023-06-01 08:26:15 -04:00
|
|
|
|
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) {
|
2023-07-17 08:15:05 -04:00
|
|
|
|
if (skip) {
|
|
|
|
|
if (key === skip) skip = ''
|
|
|
|
|
continue
|
|
|
|
|
}
|
2023-06-01 08:26:15 -04:00
|
|
|
|
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`
|
|
|
|
|
)
|
|
|
|
|
}
|
2023-07-17 08:15:05 -04:00
|
|
|
|
if (!value) {
|
|
|
|
|
console.log(`Skipping ${key}`)
|
|
|
|
|
continue
|
|
|
|
|
}
|
2023-06-01 08:26:15 -04:00
|
|
|
|
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'
|
2024-07-12 09:49:31 -04:00
|
|
|
|
fs.writeFileSync(localeKeysToUploadPath, formattedKeysToUpload)
|
2023-06-01 08:26:15 -04:00
|
|
|
|
|
|
|
|
|
console.log(`"${key}": "${value}" added to ${locale}.json`)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function prompt(text) {
|
|
|
|
|
return new Promise((resolve, reject) =>
|
|
|
|
|
readline.question(text, value => {
|
|
|
|
|
resolve(value)
|
|
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-24 08:18:37 -04:00
|
|
|
|
try {
|
|
|
|
|
await translateLocales()
|
|
|
|
|
process.exit(0)
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error)
|
|
|
|
|
process.exit(1)
|
|
|
|
|
}
|