translateLocales.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. const yargs = require('yargs/yargs')
  2. const { hideBin } = require('yargs/helpers')
  3. const Path = require('path')
  4. const fs = require('fs')
  5. const LOCALES = Path.join(__dirname, '../../locales')
  6. const VALID_LOCALES = Object.keys(
  7. require('../../config/settings.defaults').translatedLanguages
  8. ).filter(locale => locale !== 'en')
  9. const readline = require('readline').createInterface({
  10. input: process.stdin,
  11. output: process.stdout,
  12. })
  13. const argv = yargs(hideBin(process.argv))
  14. .usage('Translate locales')
  15. .option('locale', {
  16. alias: 'l',
  17. type: 'string',
  18. required: 'true',
  19. description: 'Target 2-letter locale code',
  20. choices: VALID_LOCALES,
  21. })
  22. .parse()
  23. async function translateLocales() {
  24. const { locale } = argv
  25. console.log(`Looking for missing [${locale}] translations...`)
  26. const keysToUploadFolder = Path.join(__dirname, `translated-keys-to-upload`)
  27. if (!fs.existsSync(keysToUploadFolder)) {
  28. fs.mkdirSync(keysToUploadFolder)
  29. }
  30. const localeKeysToUploadPath = Path.join(keysToUploadFolder, `${locale}.json`)
  31. const keysToUpload = fs.existsSync(localeKeysToUploadPath)
  32. ? JSON.parse(fs.readFileSync(localeKeysToUploadPath, 'utf-8'))
  33. : []
  34. const englishTranslations = await loadTranslations('en')
  35. const englishKeys = Object.keys(englishTranslations)
  36. const localeTranslations = await loadTranslations(locale)
  37. const translatedKeys = Object.keys(localeTranslations)
  38. console.log(
  39. `Currently translated: ${translatedKeys.length} / ${englishKeys.length}`
  40. )
  41. for (const key of englishKeys) {
  42. const translation = localeTranslations[key]
  43. if (!translation || translation.length === 0) {
  44. let value = await prompt(
  45. `\nMissing translation for: ${key}\n"${englishTranslations[key]}"\n`
  46. )
  47. while (value.includes("'")) {
  48. value = await prompt(
  49. `\nTranslations should not contain single-quote characters, please use curvy quotes (‘ or ’) instead:\n`
  50. )
  51. }
  52. localeTranslations[key] = value
  53. const path = Path.join(LOCALES, `${locale}.json`)
  54. const sorted =
  55. JSON.stringify(
  56. localeTranslations,
  57. Object.keys(localeTranslations).sort(),
  58. 2
  59. ) + '\n'
  60. fs.writeFileSync(path, sorted)
  61. keysToUpload.push(key)
  62. const formattedKeysToUpload =
  63. JSON.stringify(Array.from(new Set(keysToUpload)), null, 2) + '\n'
  64. await fs.writeFileSync(localeKeysToUploadPath, formattedKeysToUpload)
  65. console.log(`"${key}": "${value}" added to ${locale}.json`)
  66. }
  67. }
  68. }
  69. async function loadTranslations(locale) {
  70. return JSON.parse(
  71. fs.readFileSync(Path.join(LOCALES, `${locale}.json`), 'utf-8')
  72. )
  73. }
  74. function prompt(text) {
  75. return new Promise((resolve, reject) =>
  76. readline.question(text, value => {
  77. resolve(value)
  78. })
  79. )
  80. }
  81. translateLocales()
  82. .then(() => {
  83. process.exit(0)
  84. })
  85. .catch(error => {
  86. console.error(error)
  87. process.exit(1)
  88. })