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.
Files changed (43) hide show
  1. package/.editorconfig +9 -0
  2. package/.github/PULL_REQUEST_TEMPLATE.md +53 -46
  3. package/.github/workflows/ci-cd.yml +5 -5
  4. package/.github/workflows/commitlint.yml +1 -1
  5. package/.github/workflows/daily-help-update.yml +4 -4
  6. package/.github/workflows/daily-tx-pull.yml +4 -4
  7. package/.github/workflows/signature-assistant.yml +3 -3
  8. package/.prettierignore +11 -0
  9. package/CHANGELOG.md +7 -0
  10. package/README.md +12 -12
  11. package/commitlint.config.js +3 -3
  12. package/dist/l10n.js +224 -232
  13. package/dist/l10n.js.map +1 -1
  14. package/dist/localeData.js +223 -232
  15. package/dist/localeData.js.map +1 -1
  16. package/dist/supportedLocales.js +123 -130
  17. package/dist/supportedLocales.js.map +1 -1
  18. package/eslint.config.mjs +13 -0
  19. package/lib/batch.js +10 -12
  20. package/lib/progress-logger.mjs +33 -33
  21. package/lib/transifex.js +145 -144
  22. package/lib/validate.mjs +32 -31
  23. package/package.json +7 -8
  24. package/prettier.config.mjs +3 -0
  25. package/release.config.js +13 -13
  26. package/renovate.json5 +3 -5
  27. package/scripts/build-data.mjs +33 -49
  28. package/scripts/build-i18n-src.js +29 -28
  29. package/scripts/freshdesk-api.js +129 -144
  30. package/scripts/help-utils.js +129 -139
  31. package/scripts/tx-pull-editor.mjs +54 -51
  32. package/scripts/tx-pull-help-articles.js +14 -14
  33. package/scripts/tx-pull-help-names.js +14 -14
  34. package/scripts/tx-pull-locale-articles.js +19 -19
  35. package/scripts/tx-pull-www.mjs +79 -76
  36. package/scripts/tx-push-help.mjs +87 -96
  37. package/scripts/tx-push-src.js +65 -65
  38. package/scripts/validate-extension-inputs.mjs +65 -68
  39. package/scripts/validate-translations.mjs +33 -29
  40. package/scripts/validate-www.mjs +45 -43
  41. package/src/index.mjs +4 -3
  42. package/src/locale-data.mjs +148 -150
  43. 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
- process.stdout.write('You must specify the messages dir generated by babel-plugin-react-intl.\n');
12
- process.exit(1);
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
- process.stdout.write('A destination directory must be specified.\n');
19
- process.exit(1);
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
- let defaultMessages = glob.sync(MESSAGES_PATTERN)
30
- .map((filename) => fs.readFileSync(filename, 'utf8'))
31
- .map((file) => JSON.parse(file))
32
- .reduce((collection, descriptors) => {
33
- descriptors.forEach(({id, defaultMessage, description}) => {
34
- if (Object.prototype.hasOwnProperty.call(collection, id)) {
35
- throw new Error(`Duplicate message id: ${id}`);
36
- }
37
-
38
- collection[id] = {message: defaultMessage, description: description};
39
- });
40
-
41
- return collection;
42
- }, {});
43
-
44
- mkdirp.sync(LANG_DIR);
45
- fs.writeFileSync(path.join(LANG_DIR, 'en.json'), JSON.stringify(defaultMessages, null, 2));
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))
@@ -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
- constructor (baseUrl, apiKey) {
7
- this.baseUrl = baseUrl;
8
- this._auth = 'Basic ' + new Buffer(`${apiKey}:X`).toString('base64');
9
- this.defaultHeaders = {
10
- 'Content-Type': 'application/json',
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
- * Checks the status of a response. If status is not ok, or the body is not json raise exception
18
- * @param {object} res The response object
19
- * @returns {object} the response if it is ok
20
- */
21
- checkStatus (res) {
22
- if (res.ok) {
23
- if (res.headers.get('content-type').indexOf('application/json') !== -1) {
24
- return res;
25
- }
26
- throw new Error(`response not json: ${res.headers.get('content-type')}`);
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
- listCategories () {
37
- return fetch(`${this.baseUrl}/api/v2/solutions/categories`, {headers: this.defaultHeaders})
38
- .then(this.checkStatus)
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
- listFolders (category) {
43
- return fetch(
44
- `${this.baseUrl}/api/v2/solutions/categories/${category.id}/folders`,
45
- {headers: this.defaultHeaders})
46
- .then(this.checkStatus)
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
- listArticles (folder) {
51
- return fetch(
52
- `${this.baseUrl}/api/v2/solutions/folders/${folder.id}/articles`,
53
- {headers: this.defaultHeaders})
54
- .then(this.checkStatus)
55
- .then(res => res.json());
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
- updateCategoryTranslation (id, locale, body) {
59
- if (this.rateLimited) {
60
- process.stdout.write(`Rate limited, skipping id: ${id} for ${locale}\n`);
61
- return -1;
62
- }
63
- return fetch(
64
- `${this.baseUrl}/api/v2/solutions/categories/${id}/${locale}`,
65
- {
66
- method: 'put',
67
- body: JSON.stringify(body),
68
- headers: this.defaultHeaders
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
- return fetch(
99
- `${this.baseUrl}/api/v2/solutions/folders/${id}/${locale}`,
100
- {
101
- method: 'put',
102
- body: JSON.stringify(body),
103
- headers: this.defaultHeaders
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
- return fetch(
134
- `${this.baseUrl}/api/v2/solutions/articles/${id}/${locale}`,
135
- {
136
- method: 'put',
137
- body: JSON.stringify(body),
138
- headers: this.defaultHeaders
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
- .catch((err) => {
143
- if (err.code === 404) {
144
- // not found, try create instead
145
- return fetch(
146
- `${this.baseUrl}/api/v2/solutions/articles/${id}/${locale}`,
147
- {
148
- method: 'post',
149
- body: JSON.stringify(body),
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