adapt-authoring-lang 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,10 +3,16 @@ on:
3
3
  push:
4
4
  branches:
5
5
  - master
6
+
6
7
  jobs:
7
8
  release:
8
9
  name: Release
9
10
  runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: write # to be able to publish a GitHub release
13
+ issues: write # to be able to comment on released issues
14
+ pull-requests: write # to be able to comment on released pull requests
15
+ id-token: write # to enable use of OIDC for trusted publishing and npm provenance
10
16
  steps:
11
17
  - name: Checkout
12
18
  uses: actions/checkout@v3
@@ -16,10 +22,11 @@ jobs:
16
22
  uses: actions/setup-node@v3
17
23
  with:
18
24
  node-version: 'lts/*'
25
+ - name: Update npm
26
+ run: npm install -g npm@latest
19
27
  - name: Install dependencies
20
28
  run: npm ci
21
29
  - name: Release
22
30
  env:
23
31
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
24
- NPM_TOKEN: ${{ secrets.AAT_NPM_TOKEN }}
25
- run: npx semantic-release
32
+ run: npx semantic-release
package/bin/check.js CHANGED
@@ -8,14 +8,33 @@ import path from 'path'
8
8
 
9
9
  const root = `${process.cwd().replaceAll(path.sep, '/')}/node_modules`
10
10
 
11
+ const underline = (s='', topLine=true) => {
12
+ const line = () => ''.padEnd(80, '-')
13
+ console.log(`${topLine ? line() + '\n' : ''} ${s}\n${line()}`)
14
+ }
15
+
11
16
  async function check () {
12
- console.log('Checking for unused language strings')
17
+ console.log('\n\nChecking app language strings')
13
18
 
14
19
  const translatedStrings = await getTranslatedStrings()
15
- const usedStrings = await getUsedStrings(translatedStrings)
16
20
 
17
- logUnusedStrings(translatedStrings)
18
- logMissingStrings(translatedStrings, usedStrings)
21
+ for (const lang of Object.keys(translatedStrings)) {
22
+ console.log('\n\n')
23
+ underline(`Language: ${lang}`.toUpperCase().padEnd(80), true)
24
+
25
+ const langStrings = translatedStrings[lang]
26
+ const usedStrings = await getUsedStrings(langStrings)
27
+ const unusedStrings = Object.entries(langStrings).filter(([k, v]) => !k.startsWith('error.') && !v).map(([k]) => k)
28
+ const missingStrings = Object.entries(usedStrings).filter(([key]) => !langStrings[key] && !key.startsWith('error') && key !== 'app.js')
29
+
30
+ console.log()
31
+ logStrings(unusedStrings, 'translated strings not referenced in the code')
32
+ console.log()
33
+ logStrings(missingStrings, 'strings without translation')
34
+ console.log()
35
+ underline(`Summary:\n - ${unusedStrings.length} unused language strings found\n - ${missingStrings.length} missing language strings found`.padEnd(80), true)
36
+ }
37
+ console.log()
19
38
  }
20
39
 
21
40
  async function getTranslatedStrings () {
@@ -24,11 +43,12 @@ async function getTranslatedStrings () {
24
43
  await Promise.all((langPacks).map(async l => {
25
44
  await Promise.all((await fs.readdir(l)).map(async f => {
26
45
  const keys = JSON.parse(await fs.readFile(`${l}/${f}`))
27
- const id = f.split('.')[1]
46
+ const [lang, id] = f.split('.')
47
+ if (!keyMap[lang]) keyMap[lang] = {}
28
48
  Object.keys(keys)
29
49
  .map(k => `${id}.${k}`)
30
50
  .forEach(k => {
31
- keyMap[k] = false
51
+ keyMap[lang][k] = false
32
52
  })
33
53
  }))
34
54
  }))
@@ -36,9 +56,8 @@ async function getTranslatedStrings () {
36
56
  }
37
57
 
38
58
  async function getUsedStrings (translatedStrings) {
39
- const translatedKeys = Object.keys(translatedStrings)
40
59
  const usedStrings = {}
41
- const errorFiles = await glob(`${root}/adapt-authoring-*/errors/*.json`, { absolute: true })
60
+ const errorFiles = await glob('adapt-authoring-*/errors/*.json', { cwd: root, absolute: true })
42
61
  await Promise.all(errorFiles.map(async f => {
43
62
  Object.keys(JSON.parse((await fs.readFile(f)))).forEach(e => {
44
63
  const key = `error.${e}`
@@ -46,48 +65,35 @@ async function getUsedStrings (translatedStrings) {
46
65
  usedStrings[key].add(f.replace(root, '').split('/')[1]) // only add module name for errors
47
66
  })
48
67
  }))
49
- const sourceFiles = await glob(`${root}/adapt-authoring-*/**/*.@(js|hbs)`, { absolute: true })
68
+ const sourceFiles = await glob('adapt-authoring-*/**/*.@(js|hbs)', { cwd: root, absolute: true, ignore: '**/node_modules/**' })
69
+
50
70
  await Promise.all(sourceFiles.map(async f => {
51
71
  const contents = (await fs.readFile(f)).toString()
52
- translatedKeys.forEach(k => {
53
- translatedStrings[k] = contents.includes(k) ? true : undefined
54
- })
55
- const match = contents.matchAll(/['|"|`|](app\.[\w|\.]+)\W/g)
56
- if (match) {
57
- for (const m of match) {
58
- const key = m[1]
59
- if (!usedStrings[key]) usedStrings[key] = new Set()
60
- usedStrings[key].add(f.replace(root, ''))
72
+ // Match all potential language keys in the file (app.*, error.*, etc.)
73
+ const allMatches = contents.matchAll(/(['"`])((?:app|error)\.[\w.]+)\1/g)
74
+
75
+ for (const m of allMatches) {
76
+ const key = m[2]
77
+ if (Object.hasOwn(translatedStrings, key)) {
78
+ translatedStrings[key] = true
61
79
  }
80
+ if (!usedStrings[key]) usedStrings[key] = new Set()
81
+ usedStrings[key].add(f.replace(root, ''))
62
82
  }
63
83
  }))
84
+ Object.entries(usedStrings).forEach(([k, set]) => {
85
+ usedStrings[k] = `${Array.from(set).map(s => `\n ${s}`).join('')}`
86
+ })
64
87
  return usedStrings
65
88
  }
66
89
 
67
- function logUnusedStrings (data) {
68
- const unusedKeys = Object.entries(data).filter(([k, v]) => !k.startsWith('error.') && !v).map(([k]) => k)
69
- console.log('')
70
- if (unusedKeys.length) {
71
- unusedKeys.forEach(k => console.log(`- ${k}`))
72
- console.log(`\n${unusedKeys.length} unused language strings found`)
73
- process.exitCode = 1
74
- } else {
75
- console.log('\nNo unused strings!')
76
- }
77
- }
78
-
79
- function logMissingStrings (translatedStrings, usedStrings) {
80
- console.log('')
81
- const translatedKeys = Object.keys(translatedStrings)
82
- const missingStrings = Object.entries(usedStrings).filter(([key]) => !translatedKeys.includes(key) && key !== 'app.js')
83
- if (missingStrings.length) {
84
- const sep = '\n => '
85
- missingStrings.forEach(([key, files]) => console.log(`- ${key}${sep}${Array.from(files).join(sep)}`))
86
- console.log(`\n${missingStrings.length} missing language strings found`)
87
- process.exitCode = 1
88
- } else {
89
- console.log('\nNo missing strings!')
90
+ function logStrings (strings, message) {
91
+ if (!strings.length) {
92
+ return
90
93
  }
94
+ underline(`Found ${strings.length} ${message}`)
95
+ console.log(`${strings.map(s => `\n- ${s}`).join('')}`)
96
+ process.exitCode = 1
91
97
  }
92
98
 
93
99
  check()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adapt-authoring-lang",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Localisation for the Adapt authoring tool",
5
5
  "homepage": "https://github.com/taylortom/adapt-authoring-lang",
6
6
  "license": "GPL-3.0",
@@ -14,15 +14,15 @@
14
14
  "glob": "^11.0.0"
15
15
  },
16
16
  "devDependencies": {
17
- "standard": "^17.1.0",
18
- "@semantic-release/commit-analyzer": "^9.0.2",
17
+ "@semantic-release/commit-analyzer": "^13.0.1",
19
18
  "@semantic-release/git": "^10.0.1",
20
- "@semantic-release/github": "^8.0.5",
21
- "@semantic-release/npm": "^9.0.1",
22
- "@semantic-release/release-notes-generator": "^10.0.3",
23
- "conventional-changelog-eslint": "^3.0.9",
24
- "semantic-release": "^21.0.1",
25
- "semantic-release-replace-plugin": "^1.2.7"
19
+ "@semantic-release/github": "^12.0.2",
20
+ "@semantic-release/npm": "^13.1.2",
21
+ "@semantic-release/release-notes-generator": "^14.1.0",
22
+ "conventional-changelog-eslint": "^6.0.0",
23
+ "semantic-release": "^25.0.2",
24
+ "semantic-release-replace-plugin": "^1.2.7",
25
+ "standard": "^17.1.0"
26
26
  },
27
27
  "release": {
28
28
  "plugins": [