test.mjs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /* eslint-disable no-console, prefer-arrow-callback */
  2. import path from 'node:path'
  3. import fs from 'node:fs'
  4. import { fileURLToPath } from 'node:url'
  5. import glob from 'glob'
  6. import chalk from 'chalk'
  7. import { getLocales, getPaths, omit } from './helpers.mjs'
  8. const root = fileURLToPath(new URL('../../', import.meta.url))
  9. const leadingLocaleName = 'en_US'
  10. const mode = process.argv[2]
  11. const pluginLocaleDependencies = {
  12. core: 'provider-views',
  13. }
  14. await test()
  15. .then(() => {
  16. console.log('\n')
  17. console.log('No blocking issues found')
  18. })
  19. .catch((error) => {
  20. console.error(error)
  21. process.exit(1)
  22. })
  23. function test () {
  24. switch (mode) {
  25. case 'unused':
  26. return getPaths(`${root}/packages/@uppy/**/src/locale.js`)
  27. .then((paths) => unused(getAllFilesPerPlugin(paths.map((filePath) => path.basename(path.join(filePath, '..', '..'))))))
  28. case 'warnings':
  29. return getLocales(`${root}/packages/@uppy/locales/src/*.js`)
  30. .then((locales) => warnings({
  31. leadingLocale: locales[leadingLocaleName],
  32. followerLocales: omit(locales, leadingLocaleName),
  33. }))
  34. default:
  35. return Promise.reject(new Error(`Invalid mode "${mode}"`))
  36. }
  37. }
  38. function getAllFilesPerPlugin (pluginNames) {
  39. const filesPerPlugin = {}
  40. function getFiles (name) {
  41. return glob
  42. .sync(`${root}/packages/@uppy/${name}/lib/**/*.js`)
  43. .filter((filePath) => !filePath.includes('locale.js'))
  44. .map((filePath) => fs.readFileSync(filePath, 'utf-8'))
  45. }
  46. for (const name of pluginNames) {
  47. filesPerPlugin[name] = getFiles(name)
  48. if (name in pluginLocaleDependencies) {
  49. filesPerPlugin[name].push(
  50. getFiles(pluginLocaleDependencies[name]),
  51. )
  52. }
  53. }
  54. return filesPerPlugin
  55. }
  56. async function unused (filesPerPlugin, data) {
  57. for (const [name, fileStrings] of Object.entries(filesPerPlugin)) {
  58. const fileString = fileStrings.join('\n')
  59. const localePath = path.join(
  60. root,
  61. 'packages',
  62. '@uppy',
  63. name,
  64. 'src',
  65. 'locale.js',
  66. )
  67. const locale = (await import(localePath)).default
  68. for (const key of Object.keys(locale.strings)) {
  69. const regPat = new RegExp(
  70. `(i18n|i18nArray)\\([^\\)]*['\`"]${key}['\`"]`,
  71. 'g',
  72. )
  73. if (!fileString.match(regPat)) {
  74. return Promise.reject(new Error(`Unused locale key "${key}" in @uppy/${name}`))
  75. }
  76. }
  77. }
  78. return data
  79. }
  80. function warnings ({ leadingLocale, followerLocales }) {
  81. const entries = Object.entries(followerLocales)
  82. const logs = []
  83. for (const [name, locale] of entries) {
  84. const missing = Object.keys(leadingLocale).filter((key) => !(key in locale))
  85. const excess = Object.keys(locale).filter((key) => !(key in leadingLocale))
  86. logs.push('\n')
  87. logs.push(`--> Keys from ${leadingLocaleName} missing in ${name}`)
  88. logs.push('\n')
  89. for (const key of missing) {
  90. let value = leadingLocale[key]
  91. if (typeof value === 'object') {
  92. // For values with plural forms, just take the first one right now
  93. value = value[Object.keys(value)[0]]
  94. }
  95. logs.push(
  96. [
  97. `${chalk.cyan(name)} locale has missing string: '${chalk.red(key)}'`,
  98. `that is present in ${chalk.cyan(leadingLocaleName)}`,
  99. `with value: ${chalk.yellow(value)}`,
  100. ].join(' '),
  101. )
  102. }
  103. logs.push('\n')
  104. logs.push(`--> Keys from ${name} missing in ${leadingLocaleName}`)
  105. logs.push('\n')
  106. for (const key of excess) {
  107. logs.push(
  108. [
  109. `${chalk.cyan(name)} locale has excess string:`,
  110. `'${chalk.yellow(key)}' that is not present`,
  111. `in ${chalk.cyan(leadingLocaleName)}.`,
  112. ].join(' '),
  113. )
  114. }
  115. }
  116. console.log(logs.join('\n'))
  117. }