next-intl 4.5.7 → 4.6.0
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/dist/cjs/development/ExtractorCodec-DZKNn0Zq.cjs +37 -0
- package/dist/cjs/development/JSONCodec-Dlcx71xz.cjs +41 -0
- package/dist/cjs/development/POCodec-BW-UDNcq.cjs +94 -0
- package/dist/cjs/development/plugin.cjs +28 -5
- package/dist/esm/development/extractor/ExtractionCompiler.js +22 -25
- package/dist/esm/development/extractor/catalog/CatalogLocales.js +0 -33
- package/dist/esm/development/extractor/catalog/CatalogManager.js +134 -102
- package/dist/esm/development/extractor/catalog/CatalogPersister.js +31 -13
- package/dist/esm/development/extractor/catalog/SaveScheduler.js +33 -14
- package/dist/esm/development/extractor/catalogLoader.js +10 -10
- package/dist/esm/development/extractor/extractMessages.js +9 -2
- package/dist/esm/development/extractor/extractionLoader.js +27 -4
- package/dist/esm/development/extractor/extractor/MessageExtractor.js +5 -4
- package/dist/esm/development/extractor/format/ExtractorCodec.js +5 -0
- package/dist/esm/development/extractor/format/codecs/JSONCodec.js +40 -0
- package/dist/esm/development/extractor/format/codecs/POCodec.js +93 -0
- package/dist/esm/development/extractor/format/index.js +44 -0
- package/dist/esm/development/extractor/source/SourceFileScanner.js +2 -1
- package/dist/esm/development/extractor/source/SourceFileWatcher.js +38 -0
- package/dist/esm/development/extractor/utils.js +16 -1
- package/dist/esm/development/extractor.js +1 -0
- package/dist/esm/development/plugin/createNextIntlPlugin.js +1 -1
- package/dist/esm/development/plugin/getNextConfig.js +7 -4
- package/dist/esm/production/extractor/ExtractionCompiler.js +1 -1
- package/dist/esm/production/extractor/catalog/CatalogLocales.js +1 -1
- package/dist/esm/production/extractor/catalog/CatalogManager.js +1 -1
- package/dist/esm/production/extractor/catalog/CatalogPersister.js +1 -1
- package/dist/esm/production/extractor/catalog/SaveScheduler.js +1 -1
- package/dist/esm/production/extractor/catalogLoader.js +1 -1
- package/dist/esm/production/extractor/extractMessages.js +1 -1
- package/dist/esm/production/extractor/extractionLoader.js +1 -1
- package/dist/esm/production/extractor/extractor/MessageExtractor.js +1 -1
- package/dist/esm/production/extractor/format/ExtractorCodec.js +1 -0
- package/dist/esm/production/extractor/format/codecs/JSONCodec.js +1 -0
- package/dist/esm/production/extractor/format/codecs/POCodec.js +1 -0
- package/dist/esm/production/extractor/format/index.js +1 -0
- package/dist/esm/production/extractor/source/SourceFileScanner.js +1 -1
- package/dist/esm/production/extractor/source/SourceFileWatcher.js +1 -0
- package/dist/esm/production/extractor/utils.js +1 -1
- package/dist/esm/production/extractor.js +1 -1
- package/dist/esm/production/plugin/createNextIntlPlugin.js +1 -1
- package/dist/esm/production/plugin/getNextConfig.js +1 -1
- package/dist/types/extractor/ExtractionCompiler.d.ts +5 -10
- package/dist/types/extractor/catalog/CatalogLocales.d.ts +0 -2
- package/dist/types/extractor/catalog/CatalogManager.d.ts +21 -11
- package/dist/types/extractor/catalog/CatalogPersister.d.ts +15 -6
- package/dist/types/extractor/catalog/SaveScheduler.d.ts +1 -0
- package/dist/types/extractor/extractor/MessageExtractor.d.ts +6 -6
- package/dist/types/extractor/format/ExtractorCodec.d.ts +33 -0
- package/dist/types/extractor/format/codecs/JSONCodec.d.ts +2 -0
- package/dist/types/extractor/format/codecs/POCodec.d.ts +2 -0
- package/dist/types/extractor/format/codecs/fixtures/JSONCodecStructured.d.ts +2 -0
- package/dist/types/extractor/format/codecs/fixtures/POCodecSourceMessageKey.d.ts +2 -0
- package/dist/types/extractor/format/index.d.ts +15 -0
- package/dist/types/extractor/format/types.d.ts +8 -0
- package/dist/types/extractor/index.d.ts +1 -0
- package/dist/types/extractor/source/SourceFileFilter.d.ts +1 -1
- package/dist/types/extractor/source/SourceFileScanner.d.ts +1 -1
- package/dist/types/extractor/source/SourceFileWatcher.d.ts +12 -0
- package/dist/types/extractor/types.d.ts +2 -2
- package/dist/types/extractor/utils.d.ts +3 -0
- package/dist/types/plugin/types.d.ts +1 -1
- package/package.json +6 -5
- package/dist/esm/development/extractor/formatters/Formatter.js +0 -3
- package/dist/esm/development/extractor/formatters/JSONFormatter.js +0 -42
- package/dist/esm/development/extractor/formatters/POFormatter.js +0 -51
- package/dist/esm/development/extractor/formatters/index.js +0 -6
- package/dist/esm/development/extractor/formatters/utils.js +0 -15
- package/dist/esm/production/extractor/formatters/Formatter.js +0 -1
- package/dist/esm/production/extractor/formatters/JSONFormatter.js +0 -1
- package/dist/esm/production/extractor/formatters/POFormatter.js +0 -1
- package/dist/esm/production/extractor/formatters/index.js +0 -1
- package/dist/esm/production/extractor/formatters/utils.js +0 -1
- package/dist/types/extractor/formatters/Formatter.d.ts +0 -10
- package/dist/types/extractor/formatters/JSONFormatter.d.ts +0 -10
- package/dist/types/extractor/formatters/POFormatter.d.ts +0 -10
- package/dist/types/extractor/formatters/index.d.ts +0 -5
- package/dist/types/extractor/formatters/utils.d.ts +0 -2
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Essentialls lodash/set, but we avoid this dependency
|
|
4
|
+
function setNestedProperty(obj, keyPath, value) {
|
|
5
|
+
const keys = keyPath.split('.');
|
|
6
|
+
let current = obj;
|
|
7
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
8
|
+
const key = keys[i];
|
|
9
|
+
if (!(key in current) || typeof current[key] !== 'object' || current[key] === null) {
|
|
10
|
+
current[key] = {};
|
|
11
|
+
}
|
|
12
|
+
current = current[key];
|
|
13
|
+
}
|
|
14
|
+
current[keys[keys.length - 1]] = value;
|
|
15
|
+
}
|
|
16
|
+
function getSortedMessages(messages) {
|
|
17
|
+
return messages.toSorted((messageA, messageB) => {
|
|
18
|
+
const pathA = messageA.references?.[0]?.path ?? '';
|
|
19
|
+
const pathB = messageB.references?.[0]?.path ?? '';
|
|
20
|
+
if (pathA === pathB) {
|
|
21
|
+
return localeCompare(messageA.id, messageB.id);
|
|
22
|
+
} else {
|
|
23
|
+
return localeCompare(pathA, pathB);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function localeCompare(a, b) {
|
|
28
|
+
return a.localeCompare(b, 'en');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function defineCodec(factory) {
|
|
32
|
+
return factory;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
exports.defineCodec = defineCodec;
|
|
36
|
+
exports.getSortedMessages = getSortedMessages;
|
|
37
|
+
exports.setNestedProperty = setNestedProperty;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var ExtractorCodec = require('./ExtractorCodec-DZKNn0Zq.cjs');
|
|
4
|
+
|
|
5
|
+
var JSONCodec = ExtractorCodec.defineCodec(() => ({
|
|
6
|
+
decode(source) {
|
|
7
|
+
const json = JSON.parse(source);
|
|
8
|
+
const messages = [];
|
|
9
|
+
traverseMessages(json, (message, id) => {
|
|
10
|
+
messages.push({
|
|
11
|
+
id,
|
|
12
|
+
message
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
return messages;
|
|
16
|
+
},
|
|
17
|
+
encode(messages) {
|
|
18
|
+
const root = {};
|
|
19
|
+
for (const message of ExtractorCodec.getSortedMessages(messages)) {
|
|
20
|
+
ExtractorCodec.setNestedProperty(root, message.id, message.message);
|
|
21
|
+
}
|
|
22
|
+
return JSON.stringify(root, null, 2) + '\n';
|
|
23
|
+
},
|
|
24
|
+
toJSONString(source) {
|
|
25
|
+
return source;
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
28
|
+
function traverseMessages(obj, callback, path = '') {
|
|
29
|
+
const NAMESPACE_SEPARATOR = '.';
|
|
30
|
+
for (const key of Object.keys(obj)) {
|
|
31
|
+
const newPath = path ? path + NAMESPACE_SEPARATOR + key : key;
|
|
32
|
+
const value = obj[key];
|
|
33
|
+
if (typeof value === 'string') {
|
|
34
|
+
callback(value, newPath);
|
|
35
|
+
} else if (typeof value === 'object') {
|
|
36
|
+
traverseMessages(value, callback, newPath);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
exports.default = JSONCodec;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var POParser = require('po-parser');
|
|
4
|
+
var ExtractorCodec = require('./ExtractorCodec-DZKNn0Zq.cjs');
|
|
5
|
+
|
|
6
|
+
var POCodec = ExtractorCodec.defineCodec(() => {
|
|
7
|
+
// See also https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html
|
|
8
|
+
const DEFAULT_METADATA = {
|
|
9
|
+
// Recommended by spec
|
|
10
|
+
'Content-Type': 'text/plain; charset=utf-8',
|
|
11
|
+
'Content-Transfer-Encoding': '8bit',
|
|
12
|
+
// Otherwise other tools might set this
|
|
13
|
+
'X-Generator': 'next-intl',
|
|
14
|
+
// Crowdin defaults to using msgid as source key
|
|
15
|
+
'X-Crowdin-SourceKey': 'msgstr'
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Move all parts before the last dot to msgctxt
|
|
19
|
+
const NAMESPACE_SEPARATOR = '.';
|
|
20
|
+
|
|
21
|
+
// Metadata is stored so it can be retained when writing
|
|
22
|
+
const metadataByLocale = new Map();
|
|
23
|
+
return {
|
|
24
|
+
decode(content, context) {
|
|
25
|
+
const catalog = POParser.parse(content);
|
|
26
|
+
if (catalog.meta) {
|
|
27
|
+
metadataByLocale.set(context.locale, catalog.meta);
|
|
28
|
+
}
|
|
29
|
+
const messages = catalog.messages || [];
|
|
30
|
+
return messages.map(msg => {
|
|
31
|
+
const {
|
|
32
|
+
extractedComments,
|
|
33
|
+
msgctxt,
|
|
34
|
+
msgid,
|
|
35
|
+
msgstr,
|
|
36
|
+
...rest
|
|
37
|
+
} = msg;
|
|
38
|
+
if (extractedComments && extractedComments.length > 1) {
|
|
39
|
+
throw new Error(`Multiple extracted comments are not supported. Found ${extractedComments.length} comments for msgid "${msgid}".`);
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
...rest,
|
|
43
|
+
id: msgctxt ? [msgctxt, msgid].join(NAMESPACE_SEPARATOR) : msgid,
|
|
44
|
+
message: msgstr,
|
|
45
|
+
...(extractedComments && extractedComments.length > 0 && {
|
|
46
|
+
description: extractedComments[0]
|
|
47
|
+
})
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
},
|
|
51
|
+
encode(messages, context) {
|
|
52
|
+
const encodedMessages = ExtractorCodec.getSortedMessages(messages).map(msg => {
|
|
53
|
+
const {
|
|
54
|
+
description,
|
|
55
|
+
id,
|
|
56
|
+
message,
|
|
57
|
+
...rest
|
|
58
|
+
} = msg;
|
|
59
|
+
const lastDotIndex = id.lastIndexOf(NAMESPACE_SEPARATOR);
|
|
60
|
+
const hasNamespace = id.includes(NAMESPACE_SEPARATOR);
|
|
61
|
+
const msgid = hasNamespace ? id.slice(lastDotIndex + NAMESPACE_SEPARATOR.length) : id;
|
|
62
|
+
return {
|
|
63
|
+
msgid,
|
|
64
|
+
msgstr: message,
|
|
65
|
+
...(description && {
|
|
66
|
+
extractedComments: [description]
|
|
67
|
+
}),
|
|
68
|
+
...(hasNamespace && {
|
|
69
|
+
msgctxt: id.slice(0, lastDotIndex)
|
|
70
|
+
}),
|
|
71
|
+
...rest
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
return POParser.serialize({
|
|
75
|
+
meta: {
|
|
76
|
+
Language: context.locale,
|
|
77
|
+
...DEFAULT_METADATA,
|
|
78
|
+
...metadataByLocale.get(context.locale)
|
|
79
|
+
},
|
|
80
|
+
messages: encodedMessages
|
|
81
|
+
});
|
|
82
|
+
},
|
|
83
|
+
toJSONString(source, context) {
|
|
84
|
+
const parsed = this.decode(source, context);
|
|
85
|
+
const messagesObject = {};
|
|
86
|
+
for (const message of parsed) {
|
|
87
|
+
ExtractorCodec.setNestedProperty(messagesObject, message.id, message.message);
|
|
88
|
+
}
|
|
89
|
+
return JSON.stringify(messagesObject);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
exports.default = POCodec;
|
|
@@ -105,6 +105,27 @@ export default messages;`;
|
|
|
105
105
|
fs.writeFileSync(declarationPath, createDeclaration(content));
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
const formats = {
|
|
109
|
+
json: {
|
|
110
|
+
codec: () => Promise.resolve().then(function () { return require('./JSONCodec-Dlcx71xz.cjs'); }),
|
|
111
|
+
extension: '.json'
|
|
112
|
+
},
|
|
113
|
+
po: {
|
|
114
|
+
codec: () => Promise.resolve().then(function () { return require('./POCodec-BW-UDNcq.cjs'); }),
|
|
115
|
+
extension: '.po'
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
function isBuiltInFormat(format) {
|
|
119
|
+
return typeof format === 'string' && format in formats;
|
|
120
|
+
}
|
|
121
|
+
function getFormatExtension(format) {
|
|
122
|
+
if (isBuiltInFormat(format)) {
|
|
123
|
+
return formats[format].extension;
|
|
124
|
+
} else {
|
|
125
|
+
return format.extension;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
108
129
|
class SourceFileFilter {
|
|
109
130
|
static EXTENSIONS = ['ts', 'tsx', 'js', 'jsx'];
|
|
110
131
|
|
|
@@ -198,7 +219,7 @@ function getNextConfig(pluginConfig, nextConfig) {
|
|
|
198
219
|
const nextIntlConfig = {};
|
|
199
220
|
function getExtractMessagesLoaderConfig() {
|
|
200
221
|
const experimental = pluginConfig.experimental;
|
|
201
|
-
if (!experimental.srcPath || !experimental
|
|
222
|
+
if (!experimental.srcPath || !pluginConfig.experimental?.messages) {
|
|
202
223
|
throwError('`srcPath` and `messages` are required when using `extractor`.');
|
|
203
224
|
}
|
|
204
225
|
return {
|
|
@@ -206,7 +227,7 @@ function getNextConfig(pluginConfig, nextConfig) {
|
|
|
206
227
|
options: {
|
|
207
228
|
srcPath: experimental.srcPath,
|
|
208
229
|
sourceLocale: experimental.extract.sourceLocale,
|
|
209
|
-
messages: experimental.messages
|
|
230
|
+
messages: pluginConfig.experimental.messages
|
|
210
231
|
}
|
|
211
232
|
};
|
|
212
233
|
}
|
|
@@ -274,7 +295,8 @@ function getNextConfig(pluginConfig, nextConfig) {
|
|
|
274
295
|
throwError('Message catalog loading requires Next.js 16 or higher.');
|
|
275
296
|
}
|
|
276
297
|
rules ??= getTurboRules();
|
|
277
|
-
|
|
298
|
+
const extension = getFormatExtension(pluginConfig.experimental.messages.format);
|
|
299
|
+
addTurboRule(rules, `*${extension}`, {
|
|
278
300
|
loaders: [getCatalogLoaderConfig()],
|
|
279
301
|
condition: {
|
|
280
302
|
path: `${pluginConfig.experimental.messages.path}/**/*`
|
|
@@ -338,8 +360,9 @@ function getNextConfig(pluginConfig, nextConfig) {
|
|
|
338
360
|
if (pluginConfig.experimental?.messages) {
|
|
339
361
|
if (!config.module) config.module = {};
|
|
340
362
|
if (!config.module.rules) config.module.rules = [];
|
|
363
|
+
const extension = getFormatExtension(pluginConfig.experimental.messages.format);
|
|
341
364
|
config.module.rules.push({
|
|
342
|
-
test: new RegExp(
|
|
365
|
+
test: new RegExp(`${extension.replace(/\./g, '\\.')}$`),
|
|
343
366
|
include: path.resolve(config.context, pluginConfig.experimental.messages.path),
|
|
344
367
|
use: [getCatalogLoaderConfig()],
|
|
345
368
|
type: 'javascript/auto'
|
|
@@ -364,7 +387,7 @@ function getNextConfig(pluginConfig, nextConfig) {
|
|
|
364
387
|
|
|
365
388
|
function initPlugin(pluginConfig, nextConfig) {
|
|
366
389
|
if (nextConfig?.i18n != null) {
|
|
367
|
-
warn("
|
|
390
|
+
warn("An `i18n` property was found in your Next.js config. This likely causes conflicts and should therefore be removed if you use the App Router.\n\nIf you're in progress of migrating from the Pages Router, you can refer to this example: https://next-intl.dev/examples#app-router-migration\n");
|
|
368
391
|
}
|
|
369
392
|
const messagesPathOrPaths = pluginConfig.experimental?.createMessagesDeclaration;
|
|
370
393
|
if (messagesPathOrPaths) {
|
|
@@ -1,41 +1,38 @@
|
|
|
1
1
|
import CatalogManager from './catalog/CatalogManager.js';
|
|
2
|
+
import MessageExtractor from './extractor/MessageExtractor.js';
|
|
2
3
|
|
|
3
4
|
class ExtractionCompiler {
|
|
4
|
-
isDevelopment = false;
|
|
5
5
|
constructor(config, opts = {}) {
|
|
6
|
-
|
|
7
|
-
this.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
this.
|
|
13
|
-
}
|
|
14
|
-
async compile(resourcePath, source) {
|
|
15
|
-
if (this.initialScanPromise) {
|
|
16
|
-
await this.initialScanPromise;
|
|
17
|
-
this.initialScanPromise = undefined;
|
|
18
|
-
}
|
|
19
|
-
const result = await this.manager.extractFileMessages(resourcePath, source);
|
|
20
|
-
if (this.isDevelopment && result.changed) {
|
|
21
|
-
// While we await the AST modification, we
|
|
22
|
-
// don't need to await the persistence
|
|
23
|
-
void this.manager.save();
|
|
24
|
-
}
|
|
25
|
-
return result;
|
|
6
|
+
const extractor = opts.extractor ?? new MessageExtractor(opts);
|
|
7
|
+
this.manager = new CatalogManager(config, {
|
|
8
|
+
...opts,
|
|
9
|
+
extractor
|
|
10
|
+
});
|
|
11
|
+
this[Symbol.dispose] = this[Symbol.dispose].bind(this);
|
|
12
|
+
this.installExitHandlers();
|
|
26
13
|
}
|
|
27
|
-
async
|
|
14
|
+
async extractAll() {
|
|
28
15
|
// We can't rely on all files being compiled (e.g. due to persistent
|
|
29
16
|
// caching), so loading the messages initially is necessary.
|
|
30
17
|
await this.manager.loadMessages();
|
|
31
18
|
await this.manager.save();
|
|
32
19
|
}
|
|
33
|
-
async extract() {
|
|
34
|
-
await this.initialScanPromise;
|
|
35
|
-
}
|
|
36
20
|
[Symbol.dispose]() {
|
|
21
|
+
this.uninstallExitHandlers();
|
|
37
22
|
this.manager.destroy();
|
|
38
23
|
}
|
|
24
|
+
installExitHandlers() {
|
|
25
|
+
const cleanup = this[Symbol.dispose];
|
|
26
|
+
process.on('exit', cleanup);
|
|
27
|
+
process.on('SIGINT', cleanup);
|
|
28
|
+
process.on('SIGTERM', cleanup);
|
|
29
|
+
}
|
|
30
|
+
uninstallExitHandlers() {
|
|
31
|
+
const cleanup = this[Symbol.dispose];
|
|
32
|
+
process.off('exit', cleanup);
|
|
33
|
+
process.off('SIGINT', cleanup);
|
|
34
|
+
process.off('SIGTERM', cleanup);
|
|
35
|
+
}
|
|
39
36
|
}
|
|
40
37
|
|
|
41
38
|
export { ExtractionCompiler as default };
|
|
@@ -3,7 +3,6 @@ import fs from 'fs/promises';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
|
|
5
5
|
class CatalogLocales {
|
|
6
|
-
cleanupHandlers = [];
|
|
7
6
|
onChangeCallbacks = (() => new Set())();
|
|
8
7
|
constructor(params) {
|
|
9
8
|
this.messagesDir = params.messagesDir;
|
|
@@ -58,17 +57,12 @@ class CatalogLocales {
|
|
|
58
57
|
void this.onChange();
|
|
59
58
|
}
|
|
60
59
|
});
|
|
61
|
-
this.setupCleanupHandlers();
|
|
62
60
|
}
|
|
63
61
|
stopWatcher() {
|
|
64
62
|
if (this.watcher) {
|
|
65
63
|
this.watcher.close();
|
|
66
64
|
this.watcher = undefined;
|
|
67
65
|
}
|
|
68
|
-
for (const handler of this.cleanupHandlers) {
|
|
69
|
-
handler();
|
|
70
|
-
}
|
|
71
|
-
this.cleanupHandlers = [];
|
|
72
66
|
}
|
|
73
67
|
async onChange() {
|
|
74
68
|
const oldLocales = new Set(this.targetLocales || []);
|
|
@@ -85,33 +79,6 @@ class CatalogLocales {
|
|
|
85
79
|
}
|
|
86
80
|
}
|
|
87
81
|
}
|
|
88
|
-
setupCleanupHandlers() {
|
|
89
|
-
const cleanup = () => {
|
|
90
|
-
if (this.watcher) {
|
|
91
|
-
this.watcher.close();
|
|
92
|
-
this.watcher = undefined;
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
function exitHandler() {
|
|
96
|
-
cleanup();
|
|
97
|
-
}
|
|
98
|
-
function sigintHandler() {
|
|
99
|
-
cleanup();
|
|
100
|
-
process.exit(0);
|
|
101
|
-
}
|
|
102
|
-
function sigtermHandler() {
|
|
103
|
-
cleanup();
|
|
104
|
-
process.exit(0);
|
|
105
|
-
}
|
|
106
|
-
process.once('exit', exitHandler);
|
|
107
|
-
process.once('SIGINT', sigintHandler);
|
|
108
|
-
process.once('SIGTERM', sigtermHandler);
|
|
109
|
-
this.cleanupHandlers.push(() => {
|
|
110
|
-
process.removeListener('exit', exitHandler);
|
|
111
|
-
process.removeListener('SIGINT', sigintHandler);
|
|
112
|
-
process.removeListener('SIGTERM', sigtermHandler);
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
82
|
}
|
|
116
83
|
|
|
117
84
|
export { CatalogLocales as default };
|