scratch-l10n 5.0.231 → 5.0.232
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/.editorconfig +9 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +53 -46
- package/.github/workflows/ci-cd.yml +5 -5
- package/.github/workflows/commitlint.yml +1 -1
- package/.github/workflows/daily-help-update.yml +4 -4
- package/.github/workflows/daily-tx-pull.yml +4 -4
- package/.github/workflows/signature-assistant.yml +3 -3
- package/.prettierignore +11 -0
- package/CHANGELOG.md +7 -0
- package/README.md +12 -12
- package/commitlint.config.js +3 -3
- package/dist/l10n.js +224 -232
- package/dist/l10n.js.map +1 -1
- package/dist/localeData.js +223 -232
- package/dist/localeData.js.map +1 -1
- package/dist/supportedLocales.js +123 -130
- package/dist/supportedLocales.js.map +1 -1
- package/eslint.config.mjs +13 -0
- package/lib/batch.js +10 -12
- package/lib/progress-logger.mjs +33 -33
- package/lib/transifex.js +145 -144
- package/lib/validate.mjs +32 -31
- package/package.json +7 -8
- package/prettier.config.mjs +3 -0
- package/release.config.js +13 -13
- package/renovate.json5 +3 -5
- package/scripts/build-data.mjs +33 -49
- package/scripts/build-i18n-src.js +29 -28
- package/scripts/freshdesk-api.js +129 -144
- package/scripts/help-utils.js +129 -139
- package/scripts/tx-pull-editor.mjs +54 -51
- package/scripts/tx-pull-help-articles.js +14 -14
- package/scripts/tx-pull-help-names.js +14 -14
- package/scripts/tx-pull-locale-articles.js +19 -19
- package/scripts/tx-pull-www.mjs +79 -76
- package/scripts/tx-push-help.mjs +87 -96
- package/scripts/tx-push-src.js +65 -65
- package/scripts/validate-extension-inputs.mjs +65 -68
- package/scripts/validate-translations.mjs +33 -29
- package/scripts/validate-www.mjs +45 -43
- package/src/index.mjs +4 -3
- package/src/locale-data.mjs +148 -150
- package/src/supported-locales.mjs +124 -131
@@ -1,45 +1,46 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
2
|
|
3
|
-
const fs = require('fs')
|
4
|
-
const glob = require('glob')
|
5
|
-
const path = require('path')
|
6
|
-
const mkdirp = require('mkdirp')
|
3
|
+
const fs = require('fs')
|
4
|
+
const glob = require('glob')
|
5
|
+
const path = require('path')
|
6
|
+
const mkdirp = require('mkdirp')
|
7
7
|
|
8
|
-
var args = process.argv.slice(2)
|
8
|
+
var args = process.argv.slice(2)
|
9
9
|
|
10
10
|
if (!args.length) {
|
11
|
-
|
12
|
-
|
11
|
+
process.stdout.write('You must specify the messages dir generated by babel-plugin-react-intl.\n')
|
12
|
+
process.exit(1)
|
13
13
|
}
|
14
14
|
|
15
|
-
const MESSAGES_PATTERN = args.shift() + '/**/*.json'
|
15
|
+
const MESSAGES_PATTERN = args.shift() + '/**/*.json'
|
16
16
|
|
17
17
|
if (!args.length) {
|
18
|
-
|
19
|
-
|
18
|
+
process.stdout.write('A destination directory must be specified.\n')
|
19
|
+
process.exit(1)
|
20
20
|
}
|
21
21
|
|
22
|
-
const LANG_DIR = args.shift()
|
22
|
+
const LANG_DIR = args.shift()
|
23
23
|
|
24
24
|
// Aggregates the default messages that were extracted from the example app's
|
25
25
|
// React components via the React Intl Babel plugin. An error will be thrown if
|
26
26
|
// there are messages in different components that use the same `id`. The result
|
27
27
|
// is a chromei18n format collection of `id: {message: defaultMessage,
|
28
28
|
// description: description}` pairs for the app's default locale.
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
29
|
+
const defaultMessages = glob
|
30
|
+
.sync(MESSAGES_PATTERN)
|
31
|
+
.map(filename => fs.readFileSync(filename, 'utf8'))
|
32
|
+
.map(file => JSON.parse(file))
|
33
|
+
.reduce((collection, descriptors) => {
|
34
|
+
descriptors.forEach(({ id, defaultMessage, description }) => {
|
35
|
+
if (Object.prototype.hasOwnProperty.call(collection, id)) {
|
36
|
+
throw new Error(`Duplicate message id: ${id}`)
|
37
|
+
}
|
38
|
+
|
39
|
+
collection[id] = { message: defaultMessage, description: description }
|
40
|
+
})
|
41
|
+
|
42
|
+
return collection
|
43
|
+
}, {})
|
44
|
+
|
45
|
+
mkdirp.sync(LANG_DIR)
|
46
|
+
fs.writeFileSync(path.join(LANG_DIR, 'en.json'), JSON.stringify(defaultMessages, null, 2))
|
package/scripts/freshdesk-api.js
CHANGED
@@ -1,164 +1,149 @@
|
|
1
1
|
// interface to FreshDesk Solutions (knowledge base) api
|
2
2
|
|
3
|
-
const fetch = require('node-fetch')
|
3
|
+
const fetch = require('node-fetch')
|
4
4
|
class FreshdeskApi {
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
'Authorization': this._auth
|
12
|
-
};
|
13
|
-
this.rateLimited = false;
|
5
|
+
constructor(baseUrl, apiKey) {
|
6
|
+
this.baseUrl = baseUrl
|
7
|
+
this._auth = 'Basic ' + new Buffer(`${apiKey}:X`).toString('base64')
|
8
|
+
this.defaultHeaders = {
|
9
|
+
'Content-Type': 'application/json',
|
10
|
+
Authorization: this._auth,
|
14
11
|
}
|
12
|
+
this.rateLimited = false
|
13
|
+
}
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
}
|
28
|
-
let err = new Error(`response ${res.statusText}`);
|
29
|
-
err.code = res.status;
|
30
|
-
if (res.status === 429) {
|
31
|
-
err.retryAfter = res.headers.get('Retry-After');
|
32
|
-
}
|
33
|
-
throw err;
|
15
|
+
/**
|
16
|
+
* Checks the status of a response. If status is not ok, or the body is not json raise exception
|
17
|
+
* @param {object} res The response object
|
18
|
+
* @returns {object} the response if it is ok
|
19
|
+
*/
|
20
|
+
checkStatus(res) {
|
21
|
+
if (res.ok) {
|
22
|
+
if (res.headers.get('content-type').indexOf('application/json') !== -1) {
|
23
|
+
return res
|
24
|
+
}
|
25
|
+
throw new Error(`response not json: ${res.headers.get('content-type')}`)
|
34
26
|
}
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
.then(res => res.json());
|
27
|
+
const err = new Error(`response ${res.statusText}`)
|
28
|
+
err.code = res.status
|
29
|
+
if (res.status === 429) {
|
30
|
+
err.retryAfter = res.headers.get('Retry-After')
|
40
31
|
}
|
32
|
+
throw err
|
33
|
+
}
|
41
34
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
.then(res => res.json());
|
48
|
-
}
|
35
|
+
listCategories() {
|
36
|
+
return fetch(`${this.baseUrl}/api/v2/solutions/categories`, { headers: this.defaultHeaders })
|
37
|
+
.then(this.checkStatus)
|
38
|
+
.then(res => res.json())
|
39
|
+
}
|
49
40
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
41
|
+
listFolders(category) {
|
42
|
+
return fetch(`${this.baseUrl}/api/v2/solutions/categories/${category.id}/folders`, {
|
43
|
+
headers: this.defaultHeaders,
|
44
|
+
})
|
45
|
+
.then(this.checkStatus)
|
46
|
+
.then(res => res.json())
|
47
|
+
}
|
57
48
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
49
|
+
listArticles(folder) {
|
50
|
+
return fetch(`${this.baseUrl}/api/v2/solutions/folders/${folder.id}/articles`, { headers: this.defaultHeaders })
|
51
|
+
.then(this.checkStatus)
|
52
|
+
.then(res => res.json())
|
53
|
+
}
|
54
|
+
|
55
|
+
updateCategoryTranslation(id, locale, body) {
|
56
|
+
if (this.rateLimited) {
|
57
|
+
process.stdout.write(`Rate limited, skipping id: ${id} for ${locale}\n`)
|
58
|
+
return -1
|
59
|
+
}
|
60
|
+
return fetch(`${this.baseUrl}/api/v2/solutions/categories/${id}/${locale}`, {
|
61
|
+
method: 'put',
|
62
|
+
body: JSON.stringify(body),
|
63
|
+
headers: this.defaultHeaders,
|
64
|
+
})
|
65
|
+
.then(this.checkStatus)
|
66
|
+
.then(res => res.json())
|
67
|
+
.catch(err => {
|
68
|
+
if (err.code === 404) {
|
69
|
+
// not found, try create instead
|
70
|
+
return fetch(`${this.baseUrl}/api/v2/solutions/categories/${id}/${locale}`, {
|
71
|
+
method: 'post',
|
72
|
+
body: JSON.stringify(body),
|
73
|
+
headers: this.defaultHeaders,
|
74
|
+
})
|
70
75
|
.then(this.checkStatus)
|
71
76
|
.then(res => res.json())
|
72
|
-
.catch((err) => {
|
73
|
-
if (err.code === 404) {
|
74
|
-
// not found, try create instead
|
75
|
-
return fetch(
|
76
|
-
`${this.baseUrl}/api/v2/solutions/categories/${id}/${locale}`,
|
77
|
-
{
|
78
|
-
method: 'post',
|
79
|
-
body: JSON.stringify(body),
|
80
|
-
headers: this.defaultHeaders
|
81
|
-
})
|
82
|
-
.then(this.checkStatus)
|
83
|
-
.then(res => res.json());
|
84
|
-
}
|
85
|
-
if (err.code === 429) {
|
86
|
-
this.rateLimited = true;
|
87
|
-
}
|
88
|
-
process.stdout.write(`Error processing id ${id} for locale ${locale}: ${err.message}\n`);
|
89
|
-
throw err;
|
90
|
-
});
|
91
|
-
}
|
92
|
-
|
93
|
-
updateFolderTranslation (id, locale, body) {
|
94
|
-
if (this.rateLimited) {
|
95
|
-
process.stdout.write(`Rate limited, skipping id: ${id} for ${locale}\n`);
|
96
|
-
return -1;
|
97
77
|
}
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
78
|
+
if (err.code === 429) {
|
79
|
+
this.rateLimited = true
|
80
|
+
}
|
81
|
+
process.stdout.write(`Error processing id ${id} for locale ${locale}: ${err.message}\n`)
|
82
|
+
throw err
|
83
|
+
})
|
84
|
+
}
|
85
|
+
|
86
|
+
updateFolderTranslation(id, locale, body) {
|
87
|
+
if (this.rateLimited) {
|
88
|
+
process.stdout.write(`Rate limited, skipping id: ${id} for ${locale}\n`)
|
89
|
+
return -1
|
90
|
+
}
|
91
|
+
return fetch(`${this.baseUrl}/api/v2/solutions/folders/${id}/${locale}`, {
|
92
|
+
method: 'put',
|
93
|
+
body: JSON.stringify(body),
|
94
|
+
headers: this.defaultHeaders,
|
95
|
+
})
|
96
|
+
.then(this.checkStatus)
|
97
|
+
.then(res => res.json())
|
98
|
+
.catch(err => {
|
99
|
+
if (err.code === 404) {
|
100
|
+
// not found, try create instead
|
101
|
+
return fetch(`${this.baseUrl}/api/v2/solutions/folders/${id}/${locale}`, {
|
102
|
+
method: 'post',
|
103
|
+
body: JSON.stringify(body),
|
104
|
+
headers: this.defaultHeaders,
|
105
|
+
})
|
105
106
|
.then(this.checkStatus)
|
106
107
|
.then(res => res.json())
|
107
|
-
.catch((err) => {
|
108
|
-
if (err.code === 404) {
|
109
|
-
// not found, try create instead
|
110
|
-
return fetch(
|
111
|
-
`${this.baseUrl}/api/v2/solutions/folders/${id}/${locale}`,
|
112
|
-
{
|
113
|
-
method: 'post',
|
114
|
-
body: JSON.stringify(body),
|
115
|
-
headers: this.defaultHeaders
|
116
|
-
})
|
117
|
-
.then(this.checkStatus)
|
118
|
-
.then(res => res.json());
|
119
|
-
}
|
120
|
-
if (err.code === 429) {
|
121
|
-
this.rateLimited = true;
|
122
|
-
}
|
123
|
-
process.stdout.write(`Error processing id ${id} for locale ${locale}: ${err.message}\n`);
|
124
|
-
throw err;
|
125
|
-
});
|
126
|
-
}
|
127
|
-
|
128
|
-
updateArticleTranslation (id, locale, body) {
|
129
|
-
if (this.rateLimited) {
|
130
|
-
process.stdout.write(`Rate limited, skipping id: ${id} for ${locale}\n`);
|
131
|
-
return -1;
|
132
108
|
}
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
109
|
+
if (err.code === 429) {
|
110
|
+
this.rateLimited = true
|
111
|
+
}
|
112
|
+
process.stdout.write(`Error processing id ${id} for locale ${locale}: ${err.message}\n`)
|
113
|
+
throw err
|
114
|
+
})
|
115
|
+
}
|
116
|
+
|
117
|
+
updateArticleTranslation(id, locale, body) {
|
118
|
+
if (this.rateLimited) {
|
119
|
+
process.stdout.write(`Rate limited, skipping id: ${id} for ${locale}\n`)
|
120
|
+
return -1
|
121
|
+
}
|
122
|
+
return fetch(`${this.baseUrl}/api/v2/solutions/articles/${id}/${locale}`, {
|
123
|
+
method: 'put',
|
124
|
+
body: JSON.stringify(body),
|
125
|
+
headers: this.defaultHeaders,
|
126
|
+
})
|
127
|
+
.then(this.checkStatus)
|
128
|
+
.then(res => res.json())
|
129
|
+
.catch(err => {
|
130
|
+
if (err.code === 404) {
|
131
|
+
// not found, try create instead
|
132
|
+
return fetch(`${this.baseUrl}/api/v2/solutions/articles/${id}/${locale}`, {
|
133
|
+
method: 'post',
|
134
|
+
body: JSON.stringify(body),
|
135
|
+
headers: this.defaultHeaders,
|
136
|
+
})
|
140
137
|
.then(this.checkStatus)
|
141
138
|
.then(res => res.json())
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
headers: this.defaultHeaders
|
151
|
-
})
|
152
|
-
.then(this.checkStatus)
|
153
|
-
.then(res => res.json());
|
154
|
-
}
|
155
|
-
if (err.code === 429) {
|
156
|
-
this.rateLimited = true;
|
157
|
-
}
|
158
|
-
process.stdout.write(`Error processing id ${id} for locale ${locale}: ${err.message}\n`);
|
159
|
-
throw err;
|
160
|
-
});
|
161
|
-
}
|
139
|
+
}
|
140
|
+
if (err.code === 429) {
|
141
|
+
this.rateLimited = true
|
142
|
+
}
|
143
|
+
process.stdout.write(`Error processing id ${id} for locale ${locale}: ${err.message}\n`)
|
144
|
+
throw err
|
145
|
+
})
|
146
|
+
}
|
162
147
|
}
|
163
148
|
|
164
|
-
module.exports = FreshdeskApi
|
149
|
+
module.exports = FreshdeskApi
|