test.mjs 3.6 KB

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