@discord/intl-loader-core 0.20.1 → 0.21.1-canary.ad1c466
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/package.json +2 -2
- package/src/processing.js +35 -10
- package/src/watcher.js +29 -8
- package/types/src/processing.d.ts +15 -10
- package/types/src/watcher.d.ts +1 -1
- package/types/types.d.ts +23 -8
- package/types.d.ts +23 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@discord/intl-loader-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.1-canary.ad1c466",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Core utilities for writing loaders and transformers using @discord/intl",
|
|
6
6
|
"author": "Jon Egeland",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"chokidar": "^3.6.0",
|
|
30
30
|
"debug": "^4.3.6",
|
|
31
|
-
"@discord/intl-message-database": "0.
|
|
31
|
+
"@discord/intl-message-database": "0.21.1-canary.ad1c466"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/debug": "^4.1.12",
|
package/src/processing.js
CHANGED
|
@@ -7,6 +7,13 @@ const { database } = require('./database');
|
|
|
7
7
|
const { findAllTranslationFiles, getLocaleFromTranslationsFileName } = require('./util');
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
+
* @import {
|
|
11
|
+
* IntlMessagesFileDescriptor,
|
|
12
|
+
* IntlSourceFileInsertionData,
|
|
13
|
+
* ProcessDefinitionsResult,
|
|
14
|
+
* ProcessTranslationsResult
|
|
15
|
+
* } from '../types';
|
|
16
|
+
*
|
|
10
17
|
* @typedef {{
|
|
11
18
|
* format?: IntlCompiledMessageFormat,
|
|
12
19
|
* bundleSecrets?: boolean,
|
|
@@ -89,7 +96,7 @@ function findAllMessagesFiles(directories, defaultLocale = 'en-US') {
|
|
|
89
96
|
*
|
|
90
97
|
* @param {string[]} files
|
|
91
98
|
* @param {string} defaultLocale
|
|
92
|
-
* @returns {
|
|
99
|
+
* @returns {IntlMessagesFileDescriptor[]}
|
|
93
100
|
*/
|
|
94
101
|
function filterAllMessagesFiles(files, defaultLocale = 'en-US') {
|
|
95
102
|
return database.filterAllMessagesFiles(files, defaultLocale);
|
|
@@ -97,14 +104,15 @@ function filterAllMessagesFiles(files, defaultLocale = 'en-US') {
|
|
|
97
104
|
|
|
98
105
|
/**
|
|
99
106
|
* Iterate the given `files`, processing each one's content into the database. Processing is done
|
|
100
|
-
* in parallel using native acceleration, and returns
|
|
107
|
+
* in parallel using native acceleration, and returns an object describing all of the changes that
|
|
108
|
+
* were processed.
|
|
101
109
|
*
|
|
102
110
|
* Note that this method _only_ operates by reading file contents from the system, it is not
|
|
103
111
|
* possible to supply preloaded content through a Buffer in the same way as `processDefinitionsFile`
|
|
104
112
|
* with a `sourceContent` argument.
|
|
105
113
|
*
|
|
106
|
-
* @param {
|
|
107
|
-
* @returns {
|
|
114
|
+
* @param {IntlMessagesFileDescriptor[]} files
|
|
115
|
+
* @returns {IntlSourceFileInsertionData[]}
|
|
108
116
|
*/
|
|
109
117
|
function processAllMessagesFiles(files) {
|
|
110
118
|
return database.processAllMessagesFiles(files);
|
|
@@ -117,7 +125,7 @@ function processAllMessagesFiles(files) {
|
|
|
117
125
|
* processTranslations?: boolean,
|
|
118
126
|
* locale?: string
|
|
119
127
|
* }=} options
|
|
120
|
-
* @returns {
|
|
128
|
+
* @returns {ProcessDefinitionsResult}
|
|
121
129
|
*/
|
|
122
130
|
function processDefinitionsFile(sourcePath, sourceContent, options = {}) {
|
|
123
131
|
const {
|
|
@@ -127,10 +135,15 @@ function processDefinitionsFile(sourcePath, sourceContent, options = {}) {
|
|
|
127
135
|
} = options;
|
|
128
136
|
debug(`[${sourcePath}] Processing definitions with locale "${locale}"`);
|
|
129
137
|
|
|
138
|
+
/** @type {IntlSourceFileInsertionData} */
|
|
139
|
+
let result;
|
|
130
140
|
if (sourceContent != null) {
|
|
131
|
-
database.processDefinitionsFileContent(sourcePath, sourceContent, locale);
|
|
141
|
+
result = database.processDefinitionsFileContent(sourcePath, sourceContent, locale);
|
|
132
142
|
} else {
|
|
133
|
-
database.processDefinitionsFile(sourcePath, locale);
|
|
143
|
+
result = database.processDefinitionsFile(sourcePath, locale);
|
|
144
|
+
}
|
|
145
|
+
if (result.errors.length > 0) {
|
|
146
|
+
return { succeeded: false, errors: result.errors };
|
|
134
147
|
}
|
|
135
148
|
|
|
136
149
|
const sourceFile = database.getSourceFile(sourcePath);
|
|
@@ -151,10 +164,15 @@ function processDefinitionsFile(sourcePath, sourceContent, options = {}) {
|
|
|
151
164
|
|
|
152
165
|
if (processTranslations) {
|
|
153
166
|
const translationsResult = database.processAllTranslationFiles(translationsLocaleMap);
|
|
167
|
+
const allErrors = translationsResult.flatMap((result) => result.errors);
|
|
168
|
+
if (allErrors.length > 0) {
|
|
169
|
+
return { succeeded: false, errors: allErrors };
|
|
170
|
+
}
|
|
154
171
|
debug('[${sourcePath}] Finished processing all translations: %O', translationsResult);
|
|
155
172
|
}
|
|
156
173
|
|
|
157
174
|
return {
|
|
175
|
+
succeeded: true,
|
|
158
176
|
sourceFile,
|
|
159
177
|
locale,
|
|
160
178
|
messageKeys,
|
|
@@ -170,14 +188,20 @@ function processDefinitionsFile(sourcePath, sourceContent, options = {}) {
|
|
|
170
188
|
* @param {{
|
|
171
189
|
* locale?: string,
|
|
172
190
|
* }=} options
|
|
173
|
-
* @returns {
|
|
191
|
+
* @returns {ProcessTranslationsResult}
|
|
174
192
|
*/
|
|
175
193
|
function processTranslationsFile(sourcePath, sourceContent, options = {}) {
|
|
176
194
|
const { locale = getLocaleFromTranslationsFileName(sourcePath) } = options;
|
|
195
|
+
|
|
196
|
+
/** @type {IntlSourceFileInsertionData} */
|
|
197
|
+
let result;
|
|
177
198
|
if (sourceContent) {
|
|
178
|
-
database.processTranslationFileContent(sourcePath, locale, sourceContent);
|
|
199
|
+
result = database.processTranslationFileContent(sourcePath, locale, sourceContent);
|
|
179
200
|
} else {
|
|
180
|
-
database.processTranslationFile(sourcePath, locale);
|
|
201
|
+
result = database.processTranslationFile(sourcePath, locale);
|
|
202
|
+
}
|
|
203
|
+
if (result.errors.length > 0) {
|
|
204
|
+
return { succeeded: false, errors: result.errors };
|
|
181
205
|
}
|
|
182
206
|
|
|
183
207
|
const sourceFile = database.getSourceFile(sourcePath);
|
|
@@ -189,6 +213,7 @@ function processTranslationsFile(sourcePath, sourceContent, options = {}) {
|
|
|
189
213
|
}
|
|
190
214
|
|
|
191
215
|
return {
|
|
216
|
+
succeeded: true,
|
|
192
217
|
sourceFile,
|
|
193
218
|
locale,
|
|
194
219
|
messageKeys: database.getSourceFileKeyMap(sourcePath),
|
package/src/watcher.js
CHANGED
|
@@ -30,7 +30,7 @@ const DEFAULT_LOCALE = 'en-US';
|
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* @typedef {{
|
|
33
|
-
* on(event: string, callback: (event: string, path: string) => void): void
|
|
33
|
+
* on(event: string, callback: (event: string, path: string) => void): void,
|
|
34
34
|
* }} BasicWatcher
|
|
35
35
|
*/
|
|
36
36
|
|
|
@@ -53,7 +53,11 @@ async function watchMessagesFiles(
|
|
|
53
53
|
) {
|
|
54
54
|
debug('Pre-initializing database with all discoverable messages files');
|
|
55
55
|
const files = findAllMessagesFiles(watchedFolders);
|
|
56
|
-
processAllMessagesFiles(files);
|
|
56
|
+
const result = processAllMessagesFiles(files);
|
|
57
|
+
const reprocessQueue = result
|
|
58
|
+
.filter((data) => data.errors.length > 0)
|
|
59
|
+
.map((data) => data.fileKey);
|
|
60
|
+
|
|
57
61
|
if (once) {
|
|
58
62
|
debug('Performing one-shot watch because `once` was true');
|
|
59
63
|
// This is a weird hack around file watching just not working well on
|
|
@@ -80,8 +84,24 @@ async function watchMessagesFiles(
|
|
|
80
84
|
ignoreInitial: skipInitial,
|
|
81
85
|
persistent: !once,
|
|
82
86
|
});
|
|
87
|
+
|
|
83
88
|
watcher.on('all', (event, path) => {
|
|
84
|
-
|
|
89
|
+
// Process the file that changed first, then reprocess all of the queued files from previous
|
|
90
|
+
// failures to hopefully get them to process successfully again.
|
|
91
|
+
const [result] = processAllMessagesFiles(filterAllMessagesFiles([path]));
|
|
92
|
+
const failed = result.errors.length > 0 ? [result.fileKey] : [];
|
|
93
|
+
const secondResult = processAllMessagesFiles(
|
|
94
|
+
filterAllMessagesFiles([...reprocessQueue, ...failed]),
|
|
95
|
+
);
|
|
96
|
+
// For any files that are still failing, keep them in the queue for next time.
|
|
97
|
+
const secondFailures = secondResult
|
|
98
|
+
.filter((data) => data.errors.length > 0)
|
|
99
|
+
.map((data) => data.fileKey);
|
|
100
|
+
if (secondFailures.length > 0) {
|
|
101
|
+
debug('Failed to re-process files: %O. Next update will try again.', secondFailures);
|
|
102
|
+
}
|
|
103
|
+
reprocessQueue.splice(0, Infinity, ...secondFailures);
|
|
104
|
+
|
|
85
105
|
debug(`watcher got event: ${event}, for path ${path}`);
|
|
86
106
|
});
|
|
87
107
|
for (const signal of ['SIGINT', 'SIGTERM', 'SIGQUIT']) {
|
|
@@ -136,16 +156,17 @@ async function precompileMessageDefinitionsFiles(
|
|
|
136
156
|
`.compiled.messages.${assetExtension}`,
|
|
137
157
|
);
|
|
138
158
|
const result = processDefinitionsFile(filePath);
|
|
159
|
+
if (!result.succeeded) {
|
|
160
|
+
debug('[INTL Error] Failed to compile messages');
|
|
161
|
+
console.error(result.errors);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
139
165
|
precompileFileForLocale(filePath, result.locale, undefined, {
|
|
140
166
|
format,
|
|
141
167
|
bundleSecrets,
|
|
142
168
|
});
|
|
143
169
|
|
|
144
|
-
database.processDefinitionsFile(filePath);
|
|
145
|
-
database.precompile(filePath, DEFAULT_LOCALE, outputPath, {
|
|
146
|
-
format: IntlCompiledMessageFormat.KeylessJson,
|
|
147
|
-
bundleSecrets,
|
|
148
|
-
});
|
|
149
170
|
debug(`Wrote definitions to: ${outputPath}`);
|
|
150
171
|
} catch (e) {
|
|
151
172
|
debug('[INTL Error] Failed to compile messages');
|
|
@@ -32,21 +32,22 @@ export function findAllMessagesFiles(directories: string[], defaultLocale?: stri
|
|
|
32
32
|
*
|
|
33
33
|
* @param {string[]} files
|
|
34
34
|
* @param {string} defaultLocale
|
|
35
|
-
* @returns {
|
|
35
|
+
* @returns {IntlMessagesFileDescriptor[]}
|
|
36
36
|
*/
|
|
37
|
-
export function filterAllMessagesFiles(files: string[], defaultLocale?: string):
|
|
37
|
+
export function filterAllMessagesFiles(files: string[], defaultLocale?: string): IntlMessagesFileDescriptor[];
|
|
38
38
|
/**
|
|
39
39
|
* Iterate the given `files`, processing each one's content into the database. Processing is done
|
|
40
|
-
* in parallel using native acceleration, and returns
|
|
40
|
+
* in parallel using native acceleration, and returns an object describing all of the changes that
|
|
41
|
+
* were processed.
|
|
41
42
|
*
|
|
42
43
|
* Note that this method _only_ operates by reading file contents from the system, it is not
|
|
43
44
|
* possible to supply preloaded content through a Buffer in the same way as `processDefinitionsFile`
|
|
44
45
|
* with a `sourceContent` argument.
|
|
45
46
|
*
|
|
46
|
-
* @param {
|
|
47
|
-
* @returns {
|
|
47
|
+
* @param {IntlMessagesFileDescriptor[]} files
|
|
48
|
+
* @returns {IntlSourceFileInsertionData[]}
|
|
48
49
|
*/
|
|
49
|
-
export function processAllMessagesFiles(files:
|
|
50
|
+
export function processAllMessagesFiles(files: IntlMessagesFileDescriptor[]): IntlSourceFileInsertionData[];
|
|
50
51
|
/**
|
|
51
52
|
* Generate a `.d.ts` file containing TypeScript type definitions for all of the messages defined in
|
|
52
53
|
* `sourcePath`. This method does not process `sourcePath` at all, meaning it expects the database
|
|
@@ -93,12 +94,12 @@ export function precompileFileForLocale(sourcePath: string, locale: string, outp
|
|
|
93
94
|
* processTranslations?: boolean,
|
|
94
95
|
* locale?: string
|
|
95
96
|
* }=} options
|
|
96
|
-
* @returns {
|
|
97
|
+
* @returns {ProcessDefinitionsResult}
|
|
97
98
|
*/
|
|
98
99
|
export function processDefinitionsFile(sourcePath: string, sourceContent?: string | undefined, options?: {
|
|
99
100
|
processTranslations?: boolean;
|
|
100
101
|
locale?: string;
|
|
101
|
-
} | undefined):
|
|
102
|
+
} | undefined): ProcessDefinitionsResult;
|
|
102
103
|
/**
|
|
103
104
|
*
|
|
104
105
|
* @param {string} sourcePath
|
|
@@ -106,9 +107,13 @@ export function processDefinitionsFile(sourcePath: string, sourceContent?: strin
|
|
|
106
107
|
* @param {{
|
|
107
108
|
* locale?: string,
|
|
108
109
|
* }=} options
|
|
109
|
-
* @returns {
|
|
110
|
+
* @returns {ProcessTranslationsResult}
|
|
110
111
|
*/
|
|
111
112
|
export function processTranslationsFile(sourcePath: string, sourceContent?: string | undefined, options?: {
|
|
112
113
|
locale?: string;
|
|
113
|
-
} | undefined):
|
|
114
|
+
} | undefined): ProcessTranslationsResult;
|
|
114
115
|
import { IntlCompiledMessageFormat } from "@discord/intl-message-database";
|
|
116
|
+
import type { IntlMessagesFileDescriptor } from '../types';
|
|
117
|
+
import type { IntlSourceFileInsertionData } from '../types';
|
|
118
|
+
import type { ProcessDefinitionsResult } from '../types';
|
|
119
|
+
import type { ProcessTranslationsResult } from '../types';
|
package/types/src/watcher.d.ts
CHANGED
package/types/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IntlSourceFile } from '@discord/intl-message-database';
|
|
1
|
+
import { IntlSourceFile, IntlSourceFileError } from '@discord/intl-message-database';
|
|
2
2
|
|
|
3
3
|
export type * from '@discord/intl-message-database';
|
|
4
4
|
|
|
@@ -72,11 +72,17 @@ export interface MessageDefinitionsTransformerOptions {
|
|
|
72
72
|
bindMode?: 'proxy' | 'literal';
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
export interface IntlProcessingError {
|
|
76
|
+
succeeded: false;
|
|
77
|
+
errors: IntlSourceFileError[];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface ProcessDefinitionsSuccess {
|
|
81
|
+
/**
|
|
82
|
+
* Whether the processing was successful as a whole. If any part of the process contained errors,
|
|
83
|
+
* including processing translations alongside the definitions file, this will be set to `false`.
|
|
84
|
+
*/
|
|
85
|
+
succeeded: true;
|
|
80
86
|
/**
|
|
81
87
|
* Direct source file from the database that was created or updated by this process.
|
|
82
88
|
*/
|
|
@@ -108,10 +114,13 @@ export interface ProcessDefinitionsResult {
|
|
|
108
114
|
}
|
|
109
115
|
|
|
110
116
|
/**
|
|
111
|
-
* The result of calling `
|
|
117
|
+
* The result of calling `processDefinitionsFile`, including the created source file, locale map,
|
|
112
118
|
* and more.
|
|
113
119
|
*/
|
|
114
|
-
export
|
|
120
|
+
export type ProcessDefinitionsResult = ProcessDefinitionsSuccess | IntlProcessingError;
|
|
121
|
+
|
|
122
|
+
export interface ProcessTranslationsSuccess {
|
|
123
|
+
succeeded: true;
|
|
115
124
|
/**
|
|
116
125
|
* Direct source file from the database that was created or updated by this process.
|
|
117
126
|
*/
|
|
@@ -128,3 +137,9 @@ export interface ProcessTranslationsResult {
|
|
|
128
137
|
*/
|
|
129
138
|
locale: string;
|
|
130
139
|
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* The result of calling `processTranslationsFile`, including the created source file, locale map,
|
|
143
|
+
* and more.
|
|
144
|
+
*/
|
|
145
|
+
export type ProcessTranslationsResult = ProcessTranslationsSuccess | IntlProcessingError;
|
package/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IntlSourceFile } from '@discord/intl-message-database';
|
|
1
|
+
import { IntlSourceFile, IntlSourceFileError } from '@discord/intl-message-database';
|
|
2
2
|
|
|
3
3
|
export type * from '@discord/intl-message-database';
|
|
4
4
|
|
|
@@ -72,11 +72,17 @@ export interface MessageDefinitionsTransformerOptions {
|
|
|
72
72
|
bindMode?: 'proxy' | 'literal';
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
export interface IntlProcessingError {
|
|
76
|
+
succeeded: false;
|
|
77
|
+
errors: IntlSourceFileError[];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface ProcessDefinitionsSuccess {
|
|
81
|
+
/**
|
|
82
|
+
* Whether the processing was successful as a whole. If any part of the process contained errors,
|
|
83
|
+
* including processing translations alongside the definitions file, this will be set to `false`.
|
|
84
|
+
*/
|
|
85
|
+
succeeded: true;
|
|
80
86
|
/**
|
|
81
87
|
* Direct source file from the database that was created or updated by this process.
|
|
82
88
|
*/
|
|
@@ -108,10 +114,13 @@ export interface ProcessDefinitionsResult {
|
|
|
108
114
|
}
|
|
109
115
|
|
|
110
116
|
/**
|
|
111
|
-
* The result of calling `
|
|
117
|
+
* The result of calling `processDefinitionsFile`, including the created source file, locale map,
|
|
112
118
|
* and more.
|
|
113
119
|
*/
|
|
114
|
-
export
|
|
120
|
+
export type ProcessDefinitionsResult = ProcessDefinitionsSuccess | IntlProcessingError;
|
|
121
|
+
|
|
122
|
+
export interface ProcessTranslationsSuccess {
|
|
123
|
+
succeeded: true;
|
|
115
124
|
/**
|
|
116
125
|
* Direct source file from the database that was created or updated by this process.
|
|
117
126
|
*/
|
|
@@ -128,3 +137,9 @@ export interface ProcessTranslationsResult {
|
|
|
128
137
|
*/
|
|
129
138
|
locale: string;
|
|
130
139
|
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* The result of calling `processTranslationsFile`, including the created source file, locale map,
|
|
143
|
+
* and more.
|
|
144
|
+
*/
|
|
145
|
+
export type ProcessTranslationsResult = ProcessTranslationsSuccess | IntlProcessingError;
|