scratch-l10n 5.0.231 → 5.0.233
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 +14 -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
package/scripts/tx-pull-www.mjs
CHANGED
@@ -1,14 +1,28 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
|
+
/**
|
3
|
+
* @file
|
4
|
+
* Script to pull www translations from transifex for all resources.
|
5
|
+
* Expects that the project and that the person running the script
|
6
|
+
* has the the TX_TOKEN environment variable set to an api
|
7
|
+
* token that has developer access.
|
8
|
+
*/
|
9
|
+
import fs from 'fs/promises'
|
10
|
+
import mkdirp from 'mkdirp'
|
11
|
+
import path from 'path'
|
12
|
+
import { batchMap } from '../lib/batch.js'
|
13
|
+
import { ProgressLogger } from '../lib/progress-logger.mjs'
|
14
|
+
import { txPull, txResources } from '../lib/transifex.js'
|
15
|
+
import locales, { localeMap } from '../src/supported-locales.mjs'
|
2
16
|
|
3
17
|
/**
|
4
|
-
* @
|
18
|
+
* @file
|
5
19
|
* Script to pull www translations from transifex for all resources.
|
6
20
|
* Expects that the project and that the person running the script
|
7
21
|
* has the the TX_TOKEN environment variable set to an api
|
8
22
|
* token that has developer access.
|
9
23
|
*/
|
10
24
|
|
11
|
-
const args = process.argv.slice(2)
|
25
|
+
const args = process.argv.slice(2)
|
12
26
|
|
13
27
|
const usage = `
|
14
28
|
Pull supported language translations from Transifex for the 'scratch-website' project.
|
@@ -18,97 +32,86 @@ const usage = `
|
|
18
32
|
path: root for the translated resources.
|
19
33
|
Each resource will be a subdirectory containing language json files.
|
20
34
|
lang: optional language code - will only pull resources for that language
|
21
|
-
NOTE: TX_TOKEN environment variable needs to be set with a Transifex API token.
|
35
|
+
NOTE: TX_TOKEN environment variable needs to be set with a Transifex API token.
|
22
36
|
See the Localization page on the GUI wiki for information about setting up Transifex.
|
23
|
-
|
37
|
+
`
|
24
38
|
// Fail immediately if the TX_TOKEN is not defined
|
25
39
|
if (!process.env.TX_TOKEN || args.length < 1) {
|
26
|
-
|
27
|
-
|
40
|
+
process.stdout.write(usage)
|
41
|
+
process.exit(1)
|
28
42
|
}
|
29
43
|
|
30
|
-
import fs from 'fs/promises';
|
31
|
-
import path from 'path';
|
32
|
-
import mkdirp from 'mkdirp';
|
33
|
-
import {txPull, txResources} from '../lib/transifex.js';
|
34
|
-
import locales, {localeMap} from '../src/supported-locales.mjs';
|
35
|
-
import {batchMap} from '../lib/batch.js';
|
36
|
-
import {ProgressLogger} from '../lib/progress-logger.mjs';
|
37
|
-
|
38
44
|
// Globals
|
39
|
-
const PROJECT = 'scratch-website'
|
40
|
-
const OUTPUT_DIR = path.resolve(args[0])
|
45
|
+
const PROJECT = 'scratch-website'
|
46
|
+
const OUTPUT_DIR = path.resolve(args[0])
|
41
47
|
// const MODE = {mode: 'reviewed'}; // default is everything for www
|
42
|
-
const CONCURRENCY_LIMIT = 36
|
48
|
+
const CONCURRENCY_LIMIT = 36
|
43
49
|
|
44
|
-
const lang = args.length === 2 ? args[1] : ''
|
50
|
+
const lang = args.length === 2 ? args[1] : ''
|
45
51
|
|
46
52
|
const getLocaleData = async function (item) {
|
47
|
-
|
48
|
-
|
49
|
-
|
53
|
+
const locale = item.locale
|
54
|
+
const resource = item.resource
|
55
|
+
const txLocale = localeMap[locale] || locale
|
50
56
|
|
51
|
-
|
57
|
+
const translations = await txPull(PROJECT, resource, txLocale)
|
52
58
|
|
53
|
-
|
54
|
-
|
59
|
+
const txOutdir = `${OUTPUT_DIR}/${PROJECT}.${resource}`
|
60
|
+
const fileName = `${txOutdir}/${locale}.json`
|
55
61
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
fileName,
|
60
|
-
JSON.stringify(translations, null, 4)
|
61
|
-
);
|
62
|
+
try {
|
63
|
+
mkdirp.sync(txOutdir)
|
64
|
+
await fs.writeFile(fileName, JSON.stringify(translations, null, 4))
|
62
65
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
};
|
68
|
-
} catch (e) {
|
69
|
-
e.cause = {
|
70
|
-
resource,
|
71
|
-
locale,
|
72
|
-
translations,
|
73
|
-
txOutdir,
|
74
|
-
fileName
|
75
|
-
};
|
76
|
-
throw e;
|
66
|
+
return {
|
67
|
+
resource,
|
68
|
+
locale,
|
69
|
+
fileName,
|
77
70
|
}
|
78
|
-
}
|
71
|
+
} catch (e) {
|
72
|
+
e.cause = {
|
73
|
+
resource,
|
74
|
+
locale,
|
75
|
+
translations,
|
76
|
+
txOutdir,
|
77
|
+
fileName,
|
78
|
+
}
|
79
|
+
throw e
|
80
|
+
}
|
81
|
+
}
|
79
82
|
|
80
|
-
const expandResourceFiles =
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
}
|
83
|
+
const expandResourceFiles = resources => {
|
84
|
+
const items = []
|
85
|
+
for (const resource of resources) {
|
86
|
+
if (lang) {
|
87
|
+
items.push({ resource: resource, locale: lang })
|
88
|
+
} else {
|
89
|
+
for (const locale of Object.keys(locales)) {
|
90
|
+
items.push({ resource: resource, locale: locale })
|
91
|
+
}
|
90
92
|
}
|
91
|
-
|
92
|
-
|
93
|
+
}
|
94
|
+
return items
|
95
|
+
}
|
93
96
|
|
94
97
|
const pullTranslations = async function () {
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
}
|
98
|
+
const resources = await txResources(PROJECT)
|
99
|
+
const allFiles = expandResourceFiles(resources)
|
100
|
+
|
101
|
+
const progress = new ProgressLogger(allFiles.length)
|
102
|
+
|
103
|
+
try {
|
104
|
+
await batchMap(allFiles, CONCURRENCY_LIMIT, async item => {
|
105
|
+
try {
|
106
|
+
await getLocaleData(item)
|
107
|
+
} finally {
|
108
|
+
progress.increment()
|
109
|
+
}
|
110
|
+
})
|
111
|
+
} catch (err) {
|
112
|
+
console.error(err)
|
113
|
+
process.exit(1)
|
114
|
+
}
|
115
|
+
}
|
113
116
|
|
114
|
-
pullTranslations()
|
117
|
+
pullTranslations()
|
package/scripts/tx-push-help.mjs
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
|
-
|
3
2
|
/**
|
4
|
-
* @
|
3
|
+
* @file
|
5
4
|
* Script get Knowledge base articles from Freshdesk and push them to transifex.
|
6
5
|
*/
|
6
|
+
import { txPush, txCreateResource } from '../lib/transifex.js'
|
7
|
+
import FreshdeskApi from './freshdesk-api.js'
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
const args = process.argv.slice(2);
|
9
|
+
const args = process.argv.slice(2)
|
11
10
|
|
12
11
|
const usage = `
|
13
12
|
Pull knowledge base articles from Freshdesk and push to scratch-help project on transifex. Usage:
|
@@ -17,129 +16,121 @@ const usage = `
|
|
17
16
|
access to the Knowledge Base.
|
18
17
|
TX_TOKEN environment variable needs to be set with a Transifex API token. See
|
19
18
|
the Localization page on the GUI wiki for information about setting up Transifex.
|
20
|
-
|
19
|
+
`
|
21
20
|
// Fail immediately if the API tokens are not defined, or there any argument
|
22
21
|
if (!process.env.TX_TOKEN || !process.env.FRESHDESK_TOKEN || args.length > 0) {
|
23
|
-
|
24
|
-
|
22
|
+
process.stdout.write(usage)
|
23
|
+
process.exit(1)
|
25
24
|
}
|
26
25
|
|
27
|
-
|
26
|
+
const FD = new FreshdeskApi('https://mitscratch.freshdesk.com', process.env.FRESHDESK_TOKEN)
|
27
|
+
const TX_PROJECT = 'scratch-help'
|
28
28
|
|
29
|
-
const
|
30
|
-
const
|
31
|
-
|
32
|
-
const categoryNames = {};
|
33
|
-
const folderNames = {};
|
29
|
+
const categoryNames = {}
|
30
|
+
const folderNames = {}
|
34
31
|
|
35
32
|
/**
|
36
33
|
* Generate a transifex id from the name and id field of an objects. Remove spaces and '/'
|
37
34
|
* from the name and append '.<id>' Transifex ids (slugs) have a max length of 50. Use at most
|
38
35
|
* 30 characters of the name to allow for Freshdesk id, and a suffix like '_json'
|
39
36
|
* @param {object} item data from Freshdesk that includes the name and id of a category or folder
|
40
|
-
* @
|
37
|
+
* @returns {string} generated transifex id
|
41
38
|
*/
|
42
|
-
const makeTxId = item => {
|
43
|
-
return `${item.name.replace(/[ /]/g, '').slice(0, 30)}_${item.id}`;
|
44
|
-
};
|
39
|
+
const makeTxId = item => `${item.name.replace(/[ /]/g, '').slice(0, 30)}_${item.id}`
|
45
40
|
|
46
41
|
const txPushResource = async (name, articles, type) => {
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
}
|
42
|
+
const resourceData = {
|
43
|
+
slug: name,
|
44
|
+
name: name,
|
45
|
+
i18n_type: type,
|
46
|
+
priority: 0, // default to normal priority
|
47
|
+
content: articles,
|
48
|
+
}
|
49
|
+
|
50
|
+
try {
|
51
|
+
await txPush(TX_PROJECT, name, articles)
|
52
|
+
} catch (err) {
|
53
|
+
if (err.statusCode !== 404) {
|
54
|
+
process.stdout.write(`Transifex Error: ${err.message}\n`)
|
55
|
+
process.stdout.write(`Transifex Error ${err.response.statusCode.toString()}: ${err.response.body}\n`)
|
56
|
+
process.exitCode = 1
|
57
|
+
return
|
58
|
+
}
|
65
59
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
}
|
60
|
+
// file not found - create it, but also give message
|
61
|
+
process.stdout.write(`Transifex Resource not found, creating: ${name}\n`)
|
62
|
+
if (err.statusCode === 404) {
|
63
|
+
await txCreateResource(TX_PROJECT, resourceData)
|
71
64
|
}
|
72
|
-
}
|
65
|
+
}
|
66
|
+
}
|
73
67
|
|
74
68
|
/**
|
75
69
|
* get a flattened list of folders associated with the specified categories
|
76
70
|
* @param {object[]} categories array of categories the folders belong to
|
77
|
-
* @
|
71
|
+
* @returns {Promise<object[]>} flattened list of folders from all requested categories
|
78
72
|
*/
|
79
|
-
const getFolders = async
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
return [].concat(...categoryFolders);
|
84
|
-
};
|
73
|
+
const getFolders = async categories => {
|
74
|
+
const categoryFolders = await Promise.all(categories.map(category => FD.listFolders(category)))
|
75
|
+
return [].concat(...categoryFolders)
|
76
|
+
}
|
85
77
|
|
86
|
-
const PUBLISHED = 2
|
78
|
+
const PUBLISHED = 2 // in Freshdesk, draft status = 1, and published = 2
|
87
79
|
|
88
80
|
/**
|
89
81
|
* Save articles in a particular folder
|
90
82
|
* @param {object} folder The folder object
|
91
83
|
*/
|
92
84
|
const saveArticles = async folder => {
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
};
|
85
|
+
await FD.listArticles(folder).then(json => {
|
86
|
+
const txArticles = json.reduce((strings, current) => {
|
87
|
+
if (current.status === PUBLISHED) {
|
88
|
+
strings[`${current.id}`] = {
|
89
|
+
title: {
|
90
|
+
string: current.title,
|
91
|
+
},
|
92
|
+
description: {
|
93
|
+
string: current.description,
|
94
|
+
},
|
95
|
+
}
|
96
|
+
if (current.tags.length > 0) {
|
97
|
+
strings[`${current.id}`].tags = { string: current.tags.toString() }
|
98
|
+
}
|
99
|
+
}
|
100
|
+
return strings
|
101
|
+
}, {})
|
102
|
+
process.stdout.write(`Push ${folder.name} articles to Transifex\n`)
|
103
|
+
txPushResource(`${makeTxId(folder)}_json`, txArticles, 'STRUCTURED_JSON')
|
104
|
+
})
|
105
|
+
}
|
115
106
|
|
116
107
|
/**
|
117
108
|
* @param {object[]} folders Array of folders containing articles to be saved
|
118
109
|
*/
|
119
|
-
const saveArticleFolders = async
|
120
|
-
|
121
|
-
}
|
110
|
+
const saveArticleFolders = async folders => {
|
111
|
+
await Promise.all(folders.map(folder => saveArticles(folder)))
|
112
|
+
}
|
122
113
|
|
123
114
|
const syncSources = async () => {
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
}
|
115
|
+
await FD.listCategories()
|
116
|
+
.then(json => {
|
117
|
+
// save category names for translation
|
118
|
+
for (const cat of json.values()) {
|
119
|
+
categoryNames[`${makeTxId(cat)}`] = cat.name
|
120
|
+
}
|
121
|
+
return json
|
122
|
+
})
|
123
|
+
.then(getFolders)
|
124
|
+
.then(data => {
|
125
|
+
data.forEach(item => {
|
126
|
+
folderNames[`${makeTxId(item)}`] = item.name
|
127
|
+
})
|
128
|
+
process.stdout.write('Push category and folder names to Transifex\n')
|
129
|
+
txPushResource('categoryNames_json', categoryNames, 'KEYVALUEJSON')
|
130
|
+
txPushResource('folderNames_json', folderNames, 'KEYVALUEJSON')
|
131
|
+
return data
|
132
|
+
})
|
133
|
+
.then(saveArticleFolders)
|
134
|
+
}
|
144
135
|
|
145
|
-
syncSources()
|
136
|
+
syncSources()
|
package/scripts/tx-push-src.js
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
2
|
|
3
3
|
/**
|
4
|
-
* @
|
4
|
+
* @file
|
5
5
|
* Script to upload a source en.json file to a particular transifex project resource.
|
6
6
|
* Expects that the project and resource have already been defined in Transifex, and that
|
7
7
|
* the person running the script has the the TX_TOKEN environment variable set to an api
|
8
8
|
* token that has developer access.
|
9
9
|
*/
|
10
10
|
|
11
|
-
const fs = require('fs')
|
12
|
-
const path = require('path')
|
13
|
-
const {txPush, txCreateResource} = require('../lib/transifex.js')
|
11
|
+
const fs = require('fs')
|
12
|
+
const path = require('path')
|
13
|
+
const { txPush, txCreateResource } = require('../lib/transifex.js')
|
14
14
|
|
15
|
-
const args = process.argv.slice(2)
|
15
|
+
const args = process.argv.slice(2)
|
16
16
|
|
17
17
|
const usage = `
|
18
18
|
Push English source strings to Transifex. Usage:
|
@@ -22,79 +22,79 @@ Push English source strings to Transifex. Usage:
|
|
22
22
|
english-json-file: path to the en.json source
|
23
23
|
NOTE: TX_TOKEN environment variable needs to be set with a Transifex API token. See
|
24
24
|
the Localization page on the GUI wiki for information about setting up Transifex.
|
25
|
-
|
25
|
+
`
|
26
26
|
|
27
27
|
// Exit if missing arguments or TX_TOKEN
|
28
28
|
if (args.length < 3 || !process.env.TX_TOKEN) {
|
29
|
-
|
30
|
-
|
29
|
+
process.stdout.write(usage)
|
30
|
+
process.exit(1)
|
31
31
|
}
|
32
32
|
|
33
33
|
// Globals
|
34
|
-
const PROJECT = args[0]
|
35
|
-
const RESOURCE = args[1]
|
34
|
+
const PROJECT = args[0]
|
35
|
+
const RESOURCE = args[1]
|
36
36
|
|
37
|
-
let en = fs.readFileSync(path.resolve(args[2]))
|
38
|
-
en = JSON.parse(en)
|
37
|
+
let en = fs.readFileSync(path.resolve(args[2]))
|
38
|
+
en = JSON.parse(en)
|
39
39
|
|
40
40
|
// get the correct resource file type based on transifex project/repo and resource
|
41
41
|
const getResourceType = (project, resource) => {
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
if (project === 'scratch-website') {
|
43
|
+
// all the resources are KEYVALUEJSON
|
44
|
+
return 'KEYVALUEJSON'
|
45
|
+
}
|
46
|
+
if (project === 'scratch-legacy') {
|
47
|
+
// all the resources are po files
|
48
|
+
return 'PO'
|
49
|
+
}
|
50
|
+
if (project === 'scratch-editor') {
|
51
|
+
if (resource === 'blocks') {
|
52
|
+
return 'KEYVALUEJSON'
|
45
53
|
}
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
if (project === 'scratch-resources') {
|
66
|
-
// all the resources are Chrome format json files
|
67
|
-
return 'CHROME';
|
68
|
-
}
|
69
|
-
process.stdout.write(`Error - Unknown resource type for:\n`);
|
70
|
-
process.stdout.write(` Project: ${project}, resource: ${resource}\n`);
|
71
|
-
process.exit(1);
|
72
|
-
};
|
54
|
+
// everything else is CHROME I18N JSON
|
55
|
+
return 'CHROME'
|
56
|
+
}
|
57
|
+
if (project === 'scratch-videos') {
|
58
|
+
// all the resources are srt files
|
59
|
+
return 'SRT'
|
60
|
+
}
|
61
|
+
if (project === 'scratch-android') {
|
62
|
+
// all the resources are android xml files
|
63
|
+
return 'ANDROID'
|
64
|
+
}
|
65
|
+
if (project === 'scratch-resources') {
|
66
|
+
// all the resources are Chrome format json files
|
67
|
+
return 'CHROME'
|
68
|
+
}
|
69
|
+
process.stdout.write(`Error - Unknown resource type for:\n`)
|
70
|
+
process.stdout.write(` Project: ${project}, resource: ${resource}\n`)
|
71
|
+
process.exit(1)
|
72
|
+
}
|
73
73
|
|
74
74
|
// update Transifex with English source
|
75
75
|
const pushSource = async function () {
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
return;
|
85
|
-
}
|
86
|
-
// file not found - create it, but also give message
|
87
|
-
process.stdout.write(`Transifex Resource not found, creating: ${RESOURCE}\n`);
|
88
|
-
const resourceData = {
|
89
|
-
slug: RESOURCE,
|
90
|
-
name: RESOURCE,
|
91
|
-
priority: 0, // default to normal priority
|
92
|
-
i18nType: getResourceType(PROJECT, RESOURCE),
|
93
|
-
content: en
|
94
|
-
};
|
95
|
-
await txCreateResource(PROJECT, resourceData);
|
96
|
-
process.exitCode = 0;
|
76
|
+
try {
|
77
|
+
await txPush(PROJECT, RESOURCE, en)
|
78
|
+
} catch (err) {
|
79
|
+
if (err.statusCode !== 404) {
|
80
|
+
process.stdout.write(`Transifex Error: ${err.message}\n`)
|
81
|
+
process.stdout.write(`Transifex Error ${err.response.statusCode.toString()}: ${err.response.body}\n`)
|
82
|
+
process.exitCode = 1
|
83
|
+
return
|
97
84
|
}
|
98
|
-
|
85
|
+
// file not found - create it, but also give message
|
86
|
+
process.stdout.write(`Transifex Resource not found, creating: ${RESOURCE}\n`)
|
87
|
+
const resourceData = {
|
88
|
+
slug: RESOURCE,
|
89
|
+
name: RESOURCE,
|
90
|
+
priority: 0, // default to normal priority
|
91
|
+
i18nType: getResourceType(PROJECT, RESOURCE),
|
92
|
+
content: en,
|
93
|
+
}
|
94
|
+
await txCreateResource(PROJECT, resourceData)
|
95
|
+
// eslint-disable-next-line require-atomic-updates -- I promise that `process` won't change across `await`
|
96
|
+
process.exitCode = 0
|
97
|
+
}
|
98
|
+
}
|
99
99
|
|
100
|
-
pushSource()
|
100
|
+
pushSource()
|