checkVariables.js 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. const fs = require('fs')
  2. const Path = require('path')
  3. const GLOBALS = ['__appName__']
  4. const LOCALES = Path.join(__dirname, '../../locales')
  5. const baseLocalePath = Path.join(LOCALES, 'en.json')
  6. const baseLocale = JSON.parse(fs.readFileSync(baseLocalePath, 'utf-8'))
  7. const baseLocaleKeys = Object.keys(baseLocale)
  8. const IGNORE_ORPHANED_TRANSLATIONS = process.argv.includes(
  9. '--ignore-orphaned-translations'
  10. )
  11. const IGNORE_NESTING_FOR = {
  12. over_x_templates_easy_getting_started: ['__templates__'],
  13. all_packages_and_templates: ['__templatesLink__'],
  14. }
  15. function fetchKeys(str) {
  16. const matches = str.matchAll(/__.*?__/g)
  17. if (matches.length === 0) {
  18. return []
  19. }
  20. return Array.from(matches).map(match => match[0])
  21. }
  22. function difference(key, base, target) {
  23. const nesting = IGNORE_NESTING_FOR[key] || []
  24. const keysInBaseButNotInTarget = base.filter(
  25. key => !target.includes(key) && !nesting.includes(key)
  26. )
  27. const keysInTargetButNotInBase = target.filter(
  28. key => !base.includes(key) && !GLOBALS.includes(key)
  29. )
  30. return {
  31. keysInBaseButNotInTarget,
  32. keysInTargetButNotInBase,
  33. }
  34. }
  35. let violations = 0
  36. for (const localeName of fs.readdirSync(LOCALES)) {
  37. if (localeName === 'README.md') continue
  38. const localePath = Path.join(LOCALES, localeName)
  39. const locale = JSON.parse(fs.readFileSync(localePath, 'utf-8'))
  40. for (const key of Object.keys(locale)) {
  41. if (!baseLocaleKeys.includes(key)) {
  42. if (IGNORE_ORPHANED_TRANSLATIONS) continue
  43. violations += 1
  44. console.warn(`[${localeName}] Orphaned key "${key}" not found in en.json`)
  45. continue
  46. }
  47. const keysInTranslation = fetchKeys(locale[key])
  48. const keysInBase = fetchKeys(baseLocale[key])
  49. const { keysInBaseButNotInTarget, keysInTargetButNotInBase } = difference(
  50. key,
  51. keysInBase,
  52. keysInTranslation
  53. )
  54. if (keysInBaseButNotInTarget.length) {
  55. violations += keysInBaseButNotInTarget.length
  56. console.warn(
  57. `[${localeName}] Missing variables in key "${key}":`,
  58. keysInBaseButNotInTarget
  59. )
  60. }
  61. if (keysInTargetButNotInBase.length) {
  62. violations += keysInTargetButNotInBase.length
  63. console.warn(
  64. `[${localeName}] Extra variables in key "${key}":`,
  65. keysInTargetButNotInBase
  66. )
  67. }
  68. }
  69. }
  70. if (violations) {
  71. console.warn('Variables are not in sync between translations.')
  72. process.exit(1)
  73. } else {
  74. console.log('Variables are in sync.')
  75. process.exit(0)
  76. }