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.
- package/.github/workflows/releases.yml +9 -2
- package/bin/check.js +47 -41
- package/package.json +9 -9
|
@@ -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
|
-
|
|
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('
|
|
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
|
-
|
|
18
|
-
|
|
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('.')
|
|
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(
|
|
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(
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
|
68
|
-
|
|
69
|
-
|
|
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.
|
|
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
|
-
"
|
|
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": "^
|
|
21
|
-
"@semantic-release/npm": "^
|
|
22
|
-
"@semantic-release/release-notes-generator": "^
|
|
23
|
-
"conventional-changelog-eslint": "^
|
|
24
|
-
"semantic-release": "^
|
|
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": [
|