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,40 @@
|
|
|
1
|
+
import { getSortedMessages, setNestedProperty } from '../../utils.js';
|
|
2
|
+
import { defineCodec } from '../ExtractorCodec.js';
|
|
3
|
+
|
|
4
|
+
var JSONCodec = defineCodec(() => ({
|
|
5
|
+
decode(source) {
|
|
6
|
+
const json = JSON.parse(source);
|
|
7
|
+
const messages = [];
|
|
8
|
+
traverseMessages(json, (message, id) => {
|
|
9
|
+
messages.push({
|
|
10
|
+
id,
|
|
11
|
+
message
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
return messages;
|
|
15
|
+
},
|
|
16
|
+
encode(messages) {
|
|
17
|
+
const root = {};
|
|
18
|
+
for (const message of getSortedMessages(messages)) {
|
|
19
|
+
setNestedProperty(root, message.id, message.message);
|
|
20
|
+
}
|
|
21
|
+
return JSON.stringify(root, null, 2) + '\n';
|
|
22
|
+
},
|
|
23
|
+
toJSONString(source) {
|
|
24
|
+
return source;
|
|
25
|
+
}
|
|
26
|
+
}));
|
|
27
|
+
function traverseMessages(obj, callback, path = '') {
|
|
28
|
+
const NAMESPACE_SEPARATOR = '.';
|
|
29
|
+
for (const key of Object.keys(obj)) {
|
|
30
|
+
const newPath = path ? path + NAMESPACE_SEPARATOR + key : key;
|
|
31
|
+
const value = obj[key];
|
|
32
|
+
if (typeof value === 'string') {
|
|
33
|
+
callback(value, newPath);
|
|
34
|
+
} else if (typeof value === 'object') {
|
|
35
|
+
traverseMessages(value, callback, newPath);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export { JSONCodec as default };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import POParser from 'po-parser';
|
|
2
|
+
import { setNestedProperty, getSortedMessages } from '../../utils.js';
|
|
3
|
+
import { defineCodec } from '../ExtractorCodec.js';
|
|
4
|
+
|
|
5
|
+
var POCodec = defineCodec(() => {
|
|
6
|
+
// See also https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html
|
|
7
|
+
const DEFAULT_METADATA = {
|
|
8
|
+
// Recommended by spec
|
|
9
|
+
'Content-Type': 'text/plain; charset=utf-8',
|
|
10
|
+
'Content-Transfer-Encoding': '8bit',
|
|
11
|
+
// Otherwise other tools might set this
|
|
12
|
+
'X-Generator': 'next-intl',
|
|
13
|
+
// Crowdin defaults to using msgid as source key
|
|
14
|
+
'X-Crowdin-SourceKey': 'msgstr'
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// Move all parts before the last dot to msgctxt
|
|
18
|
+
const NAMESPACE_SEPARATOR = '.';
|
|
19
|
+
|
|
20
|
+
// Metadata is stored so it can be retained when writing
|
|
21
|
+
const metadataByLocale = new Map();
|
|
22
|
+
return {
|
|
23
|
+
decode(content, context) {
|
|
24
|
+
const catalog = POParser.parse(content);
|
|
25
|
+
if (catalog.meta) {
|
|
26
|
+
metadataByLocale.set(context.locale, catalog.meta);
|
|
27
|
+
}
|
|
28
|
+
const messages = catalog.messages || [];
|
|
29
|
+
return messages.map(msg => {
|
|
30
|
+
const {
|
|
31
|
+
extractedComments,
|
|
32
|
+
msgctxt,
|
|
33
|
+
msgid,
|
|
34
|
+
msgstr,
|
|
35
|
+
...rest
|
|
36
|
+
} = msg;
|
|
37
|
+
if (extractedComments && extractedComments.length > 1) {
|
|
38
|
+
throw new Error(`Multiple extracted comments are not supported. Found ${extractedComments.length} comments for msgid "${msgid}".`);
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
...rest,
|
|
42
|
+
id: msgctxt ? [msgctxt, msgid].join(NAMESPACE_SEPARATOR) : msgid,
|
|
43
|
+
message: msgstr,
|
|
44
|
+
...(extractedComments && extractedComments.length > 0 && {
|
|
45
|
+
description: extractedComments[0]
|
|
46
|
+
})
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
encode(messages, context) {
|
|
51
|
+
const encodedMessages = getSortedMessages(messages).map(msg => {
|
|
52
|
+
const {
|
|
53
|
+
description,
|
|
54
|
+
id,
|
|
55
|
+
message,
|
|
56
|
+
...rest
|
|
57
|
+
} = msg;
|
|
58
|
+
const lastDotIndex = id.lastIndexOf(NAMESPACE_SEPARATOR);
|
|
59
|
+
const hasNamespace = id.includes(NAMESPACE_SEPARATOR);
|
|
60
|
+
const msgid = hasNamespace ? id.slice(lastDotIndex + NAMESPACE_SEPARATOR.length) : id;
|
|
61
|
+
return {
|
|
62
|
+
msgid,
|
|
63
|
+
msgstr: message,
|
|
64
|
+
...(description && {
|
|
65
|
+
extractedComments: [description]
|
|
66
|
+
}),
|
|
67
|
+
...(hasNamespace && {
|
|
68
|
+
msgctxt: id.slice(0, lastDotIndex)
|
|
69
|
+
}),
|
|
70
|
+
...rest
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
return POParser.serialize({
|
|
74
|
+
meta: {
|
|
75
|
+
Language: context.locale,
|
|
76
|
+
...DEFAULT_METADATA,
|
|
77
|
+
...metadataByLocale.get(context.locale)
|
|
78
|
+
},
|
|
79
|
+
messages: encodedMessages
|
|
80
|
+
});
|
|
81
|
+
},
|
|
82
|
+
toJSONString(source, context) {
|
|
83
|
+
const parsed = this.decode(source, context);
|
|
84
|
+
const messagesObject = {};
|
|
85
|
+
for (const message of parsed) {
|
|
86
|
+
setNestedProperty(messagesObject, message.id, message.message);
|
|
87
|
+
}
|
|
88
|
+
return JSON.stringify(messagesObject);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
export { POCodec as default };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { throwError } from '../../plugin/utils.js';
|
|
3
|
+
|
|
4
|
+
const formats = {
|
|
5
|
+
json: {
|
|
6
|
+
codec: () => import('./codecs/JSONCodec.js'),
|
|
7
|
+
extension: '.json'
|
|
8
|
+
},
|
|
9
|
+
po: {
|
|
10
|
+
codec: () => import('./codecs/POCodec.js'),
|
|
11
|
+
extension: '.po'
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
function isBuiltInFormat(format) {
|
|
15
|
+
return typeof format === 'string' && format in formats;
|
|
16
|
+
}
|
|
17
|
+
function getFormatExtension(format) {
|
|
18
|
+
if (isBuiltInFormat(format)) {
|
|
19
|
+
return formats[format].extension;
|
|
20
|
+
} else {
|
|
21
|
+
return format.extension;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async function resolveCodec(format, projectRoot) {
|
|
25
|
+
if (isBuiltInFormat(format)) {
|
|
26
|
+
const factory = (await formats[format].codec()).default;
|
|
27
|
+
return factory();
|
|
28
|
+
} else {
|
|
29
|
+
const resolvedPath = path.isAbsolute(format.codec) ? format.codec : path.resolve(projectRoot, format.codec);
|
|
30
|
+
let module;
|
|
31
|
+
try {
|
|
32
|
+
module = await import(resolvedPath);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
throwError(`Could not load codec from "${resolvedPath}".\n${error}`);
|
|
35
|
+
}
|
|
36
|
+
const factory = module.default;
|
|
37
|
+
if (!factory || typeof factory !== 'function') {
|
|
38
|
+
throwError(`Codec at "${resolvedPath}" must have a default export returned from \`defineCodec\`.`);
|
|
39
|
+
}
|
|
40
|
+
return factory();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { formats as default, getFormatExtension, resolveCodec };
|
|
@@ -23,7 +23,8 @@ class SourceFileScanner {
|
|
|
23
23
|
return acc;
|
|
24
24
|
}
|
|
25
25
|
static async getSourceFiles(srcPaths) {
|
|
26
|
-
|
|
26
|
+
const files = (await Promise.all(srcPaths.map(srcPath => SourceFileScanner.walkSourceFiles(srcPath, srcPaths)))).flat();
|
|
27
|
+
return new Set(files);
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { subscribe } from '@parcel/watcher';
|
|
2
|
+
import SourceFileFilter from './SourceFileFilter.js';
|
|
3
|
+
|
|
4
|
+
class SourceFileWatcher {
|
|
5
|
+
subscriptions = [];
|
|
6
|
+
constructor(roots, onChange) {
|
|
7
|
+
this.roots = roots;
|
|
8
|
+
this.onChange = onChange;
|
|
9
|
+
}
|
|
10
|
+
async start() {
|
|
11
|
+
if (this.subscriptions.length > 0) return;
|
|
12
|
+
const ignore = SourceFileFilter.IGNORED_DIRECTORIES.map(dir => `**/${dir}/**`);
|
|
13
|
+
for (const root of this.roots) {
|
|
14
|
+
const sub = await subscribe(root, (err, events) => {
|
|
15
|
+
if (err) {
|
|
16
|
+
console.error(err);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const filteredEvents = events.filter(event => SourceFileFilter.isSourceFile(event.path));
|
|
20
|
+
if (filteredEvents.length > 0) {
|
|
21
|
+
void this.onChange(filteredEvents);
|
|
22
|
+
}
|
|
23
|
+
}, {
|
|
24
|
+
ignore
|
|
25
|
+
});
|
|
26
|
+
this.subscriptions.push(sub);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async stop() {
|
|
30
|
+
await Promise.all(this.subscriptions.map(sub => sub.unsubscribe()));
|
|
31
|
+
this.subscriptions = [];
|
|
32
|
+
}
|
|
33
|
+
[Symbol.dispose]() {
|
|
34
|
+
void this.stop();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { SourceFileWatcher as default };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// Essentialls lodash/set, but we avoid this dependency
|
|
1
2
|
function setNestedProperty(obj, keyPath, value) {
|
|
2
3
|
const keys = keyPath.split('.');
|
|
3
4
|
let current = obj;
|
|
@@ -10,8 +11,22 @@ function setNestedProperty(obj, keyPath, value) {
|
|
|
10
11
|
}
|
|
11
12
|
current[keys[keys.length - 1]] = value;
|
|
12
13
|
}
|
|
14
|
+
function getSortedMessages(messages) {
|
|
15
|
+
return messages.toSorted((messageA, messageB) => {
|
|
16
|
+
const pathA = messageA.references?.[0]?.path ?? '';
|
|
17
|
+
const pathB = messageB.references?.[0]?.path ?? '';
|
|
18
|
+
if (pathA === pathB) {
|
|
19
|
+
return localeCompare(messageA.id, messageB.id);
|
|
20
|
+
} else {
|
|
21
|
+
return localeCompare(pathA, pathB);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
13
25
|
function localeCompare(a, b) {
|
|
14
26
|
return a.localeCompare(b, 'en');
|
|
15
27
|
}
|
|
28
|
+
function getDefaultProjectRoot() {
|
|
29
|
+
return process.cwd();
|
|
30
|
+
}
|
|
16
31
|
|
|
17
|
-
export { localeCompare, setNestedProperty };
|
|
32
|
+
export { getDefaultProjectRoot, getSortedMessages, localeCompare, setNestedProperty };
|
|
@@ -4,7 +4,7 @@ import createMessagesDeclaration from './declaration/createMessagesDeclaration.j
|
|
|
4
4
|
|
|
5
5
|
function initPlugin(pluginConfig, nextConfig) {
|
|
6
6
|
if (nextConfig?.i18n != null) {
|
|
7
|
-
warn("
|
|
7
|
+
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");
|
|
8
8
|
}
|
|
9
9
|
const messagesPathOrPaths = pluginConfig.experimental?.createMessagesDeclaration;
|
|
10
10
|
if (messagesPathOrPaths) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { getFormatExtension } from '../extractor/format/index.js';
|
|
3
4
|
import SourceFileFilter from '../extractor/source/SourceFileFilter.js';
|
|
4
5
|
import { isNextJs16OrHigher, hasStableTurboConfig } from './nextFlags.js';
|
|
5
6
|
import { throwError } from './utils.js';
|
|
@@ -42,7 +43,7 @@ function getNextConfig(pluginConfig, nextConfig) {
|
|
|
42
43
|
const nextIntlConfig = {};
|
|
43
44
|
function getExtractMessagesLoaderConfig() {
|
|
44
45
|
const experimental = pluginConfig.experimental;
|
|
45
|
-
if (!experimental.srcPath || !experimental
|
|
46
|
+
if (!experimental.srcPath || !pluginConfig.experimental?.messages) {
|
|
46
47
|
throwError('`srcPath` and `messages` are required when using `extractor`.');
|
|
47
48
|
}
|
|
48
49
|
return {
|
|
@@ -50,7 +51,7 @@ function getNextConfig(pluginConfig, nextConfig) {
|
|
|
50
51
|
options: {
|
|
51
52
|
srcPath: experimental.srcPath,
|
|
52
53
|
sourceLocale: experimental.extract.sourceLocale,
|
|
53
|
-
messages: experimental.messages
|
|
54
|
+
messages: pluginConfig.experimental.messages
|
|
54
55
|
}
|
|
55
56
|
};
|
|
56
57
|
}
|
|
@@ -118,7 +119,8 @@ function getNextConfig(pluginConfig, nextConfig) {
|
|
|
118
119
|
throwError('Message catalog loading requires Next.js 16 or higher.');
|
|
119
120
|
}
|
|
120
121
|
rules ??= getTurboRules();
|
|
121
|
-
|
|
122
|
+
const extension = getFormatExtension(pluginConfig.experimental.messages.format);
|
|
123
|
+
addTurboRule(rules, `*${extension}`, {
|
|
122
124
|
loaders: [getCatalogLoaderConfig()],
|
|
123
125
|
condition: {
|
|
124
126
|
path: `${pluginConfig.experimental.messages.path}/**/*`
|
|
@@ -182,8 +184,9 @@ function getNextConfig(pluginConfig, nextConfig) {
|
|
|
182
184
|
if (pluginConfig.experimental?.messages) {
|
|
183
185
|
if (!config.module) config.module = {};
|
|
184
186
|
if (!config.module.rules) config.module.rules = [];
|
|
187
|
+
const extension = getFormatExtension(pluginConfig.experimental.messages.format);
|
|
185
188
|
config.module.rules.push({
|
|
186
|
-
test: new RegExp(
|
|
189
|
+
test: new RegExp(`${extension.replace(/\./g, '\\.')}$`),
|
|
187
190
|
include: path.resolve(config.context, pluginConfig.experimental.messages.path),
|
|
188
191
|
use: [getCatalogLoaderConfig()],
|
|
189
192
|
type: 'javascript/auto'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import s from"./catalog/CatalogManager.js";import t from"./extractor/MessageExtractor.js";class o{constructor(o,a={}){const e=a.extractor??new t(a);this.manager=new s(o,{...a,extractor:e}),this[Symbol.dispose]=this[Symbol.dispose].bind(this),this.installExitHandlers()}async extractAll(){await this.manager.loadMessages(),await this.manager.save()}[Symbol.dispose](){this.uninstallExitHandlers(),this.manager.destroy()}installExitHandlers(){const s=this[Symbol.dispose];process.on("exit",s),process.on("SIGINT",s),process.on("SIGTERM",s)}uninstallExitHandlers(){const s=this[Symbol.dispose];process.off("exit",s),process.off("SIGINT",s),process.off("SIGTERM",s)}}export{o as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"fs";import s from"fs/promises";import t from"path";class a{
|
|
1
|
+
import e from"fs";import s from"fs/promises";import t from"path";class a{onChangeCallbacks=(()=>new Set)();constructor(e){this.messagesDir=e.messagesDir,this.sourceLocale=e.sourceLocale,this.extension=e.extension,this.locales=e.locales}async getTargetLocales(){return this.targetLocales||("infer"===this.locales?this.targetLocales=await this.readTargetLocales():this.targetLocales=this.locales.filter((e=>e!==this.sourceLocale))),this.targetLocales}async readTargetLocales(){try{return(await s.readdir(this.messagesDir)).filter((e=>e.endsWith(this.extension))).map((e=>t.basename(e,this.extension))).filter((e=>e!==this.sourceLocale))}catch{return[]}}subscribeLocalesChange(e){this.onChangeCallbacks.add(e),"infer"!==this.locales||this.watcher||this.startWatcher()}unsubscribeLocalesChange(e){this.onChangeCallbacks.delete(e),0===this.onChangeCallbacks.size&&this.stopWatcher()}async startWatcher(){this.watcher||(await s.mkdir(this.messagesDir,{recursive:!0}),this.watcher=e.watch(this.messagesDir,{persistent:!1,recursive:!1},((e,s)=>{null!=s&&s.endsWith(this.extension)&&!s.includes(t.sep)&&this.onChange()})))}stopWatcher(){this.watcher&&(this.watcher.close(),this.watcher=void 0)}async onChange(){const e=new Set(this.targetLocales||[]);this.targetLocales=await this.readTargetLocales();const s=new Set(this.targetLocales),t=this.targetLocales.filter((s=>!e.has(s))),a=Array.from(e).filter((e=>!s.has(e)));if(t.length>0||a.length>0)for(const e of this.onChangeCallbacks)e({added:t,removed:a})}}export{a as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"fs/promises";import s from"path";import t from"../
|
|
1
|
+
import e from"fs/promises";import s from"path";import{resolveCodec as t,getFormatExtension as a}from"../format/index.js";import o from"../source/SourceFileScanner.js";import i from"../source/SourceFileWatcher.js";import{getDefaultProjectRoot as r,localeCompare as c}from"../utils.js";import l from"./CatalogLocales.js";import n from"./CatalogPersister.js";import h from"./SaveScheduler.js";class g{messagesByFile=(()=>new Map)();messagesById=(()=>new Map)();translationsByTargetLocale=(()=>new Map)();lastWriteByLocale=(()=>new Map)();constructor(e,s){this.config=e,this.saveScheduler=new h(50),this.projectRoot=s.projectRoot??r(),this.isDevelopment=s.isDevelopment??!1,this.extractor=s.extractor,this.isDevelopment&&(this.sourceWatcher=new i(this.getSrcPaths(),this.handleFileEvents.bind(this)),this.sourceWatcher.start())}async getCodec(){return this.codec||(this.codec=await t(this.config.messages.format,this.projectRoot)),this.codec}async getPersister(){return this.persister||(this.persister=new n({messagesPath:this.config.messages.path,codec:await this.getCodec(),extension:a(this.config.messages.format)})),this.persister}getCatalogLocales(){if(this.catalogLocales)return this.catalogLocales;{const e=s.join(this.projectRoot,this.config.messages.path);return this.catalogLocales=new l({messagesDir:e,sourceLocale:this.config.sourceLocale,extension:a(this.config.messages.format),locales:this.config.messages.locales}),this.catalogLocales}}async getTargetLocales(){return this.getCatalogLocales().getTargetLocales()}getSrcPaths(){return(Array.isArray(this.config.srcPath)?this.config.srcPath:[this.config.srcPath]).map((e=>s.join(this.projectRoot,e)))}async loadMessages(){const e=await this.loadSourceMessages();this.loadCatalogsPromise=this.loadTargetMessages(),await this.loadCatalogsPromise;const s=await o.getSourceFiles(this.getSrcPaths());if(await Promise.all(Array.from(s).map((async e=>this.processFile(e)))),this.mergeSourceDiskMetadata(e),this.isDevelopment){this.getCatalogLocales().subscribeLocalesChange(this.onLocalesChange)}}async loadSourceMessages(){const e=await this.loadLocaleMessages(this.config.sourceLocale),s=new Map;for(const t of e)s.set(t.id,t);return s}async loadLocaleMessages(e){const s=await this.getPersister(),t=await s.read(e),a=await s.getLastModified(e);return this.lastWriteByLocale.set(e,a),t}async loadTargetMessages(){const e=await this.getTargetLocales();await Promise.all(e.map((e=>this.reloadLocaleCatalog(e))))}async reloadLocaleCatalog(e){const s=await this.loadLocaleMessages(e);if(e===this.config.sourceLocale)for(const e of s){const s=this.messagesById.get(e.id);if(s)for(const t of Object.keys(e))["id","message","description","references"].includes(t)||(s[t]=e[t])}else{const t=new Map;for(const e of s)t.set(e.id,e);this.translationsByTargetLocale.set(e,t)}}mergeSourceDiskMetadata(e){for(const[s,t]of e){const e=this.messagesById.get(s);if(e)for(const s of Object.keys(t))null==e[s]&&(e[s]=t[s])}}async processFile(t){let a=[];try{const s=await e.readFile(t,"utf8");a=(await this.extractor.extract(t,s)).messages}catch(e){if("ENOENT"!==e.code)throw e}const o=this.messagesByFile.get(t),i=Array.from(o?.keys()??[]),r=new Map;for(let e of a){const a=this.messagesById.get(e.id);if(a){const o=a.references??[];e={...e,references:this.mergeReferences(o,{path:s.relative(this.projectRoot,t)})};for(const s of Object.keys(a))null==e[s]&&(e[s]=a[s])}this.messagesById.set(e.id,e),r.set(e.id,e);const o=i.indexOf(e.id);-1!==o&&i.splice(o,1)}const c=s.relative(this.projectRoot,t);i.forEach((e=>{const s=this.messagesById.get(e);if(!s)return;const t=s.references?.some((e=>e.path!==c));t?s.references=s.references?.filter((e=>e.path!==c)):this.messagesById.delete(e)})),a.length>0?this.messagesByFile.set(t,r):this.messagesByFile.delete(t);return this.haveMessagesChangedForFile(o,r)}mergeReferences(e,s){const t=new Map;for(const s of e)t.set(s.path,s);return t.set(s.path,s),Array.from(t.values()).sort(((e,s)=>c(e.path,s.path)))}haveMessagesChangedForFile(e,s){if(!e)return s.size>0;if(e.size!==s.size)return!0;for(const[t,a]of e){const e=s.get(t);if(!e||!this.areMessagesEqual(a,e))return!0}return!1}areMessagesEqual(e,s){return e.id===s.id&&e.message===s.message&&e.description===s.description}async save(){return this.saveScheduler.schedule((()=>this.saveImpl()))}async saveImpl(){await this.saveLocale(this.config.sourceLocale);const e=await this.getTargetLocales();await Promise.all(e.map((e=>this.saveLocale(e))))}async saveLocale(e){await this.loadCatalogsPromise;const s=Array.from(this.messagesById.values()),t=await this.getPersister(),a=e===this.config.sourceLocale,o=this.lastWriteByLocale.get(e),i=await t.getLastModified(e);i&&o&&i>o&&await this.reloadLocaleCatalog(e);const r=a?this.messagesById:this.translationsByTargetLocale.get(e),c=s.map((e=>{const s=r?.get(e.id);return{...s,id:e.id,description:e.description,references:e.references,message:a?e.message:s?.message??""}}));await t.write(c,{locale:e,sourceMessagesById:this.messagesById});const l=await t.getLastModified(e);this.lastWriteByLocale.set(e,l)}onLocalesChange=async e=>{this.loadCatalogsPromise=Promise.all([this.loadCatalogsPromise,...e.added.map((e=>this.reloadLocaleCatalog(e)))]);for(const s of e.added)await this.saveLocale(s);for(const s of e.removed)this.translationsByTargetLocale.delete(s),this.lastWriteByLocale.delete(s)};async handleFileEvents(e){this.loadCatalogsPromise&&await this.loadCatalogsPromise;let s=!1;for(const t of e){const e=await this.processFile(t.path);s||=e}s&&await this.save()}destroy(){this.sourceWatcher?.stop(),this.sourceWatcher=void 0,this.saveScheduler.destroy(),this.catalogLocales&&this.isDevelopment&&this.catalogLocales.unsubscribeLocalesChange(this.onLocalesChange)}}export{g as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import e from"fs/promises";import t from"path";class r{constructor(e){this.messagesPath=e.messagesPath,this.codec=e.codec,this.extension=e.extension}getFileName(e){return e+this.extension}getFilePath(e){return t.join(this.messagesPath,this.getFileName(e))}async read(t){const r=this.getFilePath(t);let i;try{i=await e.readFile(r,"utf8")}catch(e){if(e&&"object"==typeof e&&"code"in e&&"ENOENT"===e.code)return[];throw new Error(`Error while reading ${this.getFileName(t)}:\n> ${e}`,{cause:e})}try{return this.codec.decode(i,{locale:t})}catch(e){throw new Error(`Error while decoding ${this.getFileName(t)}:\n> ${e}`,{cause:e})}}async write(r,i){const a=this.getFilePath(i.locale),s=this.codec.encode(r,i);try{const r=t.dirname(a);await e.mkdir(r,{recursive:!0}),await e.writeFile(a,s)}catch(e){console.error(`❌ Failed to write catalog: ${e}`)}}async getLastModified(t){const r=this.getFilePath(t);try{return(await e.stat(r)).mtime}catch{return}}}export{r as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
class e{isSaving=!1;pendingResolvers=[];constructor(e=50){this.delayMs=e}async schedule(e){return new Promise(((s,i)=>{this.pendingResolvers.push({resolve:s,reject:i}),
|
|
1
|
+
class e{isSaving=!1;pendingResolvers=[];constructor(e=50){this.delayMs=e}async schedule(e){return new Promise(((s,i)=>{this.pendingResolvers.push({resolve:s,reject:i}),this.nextSaveTask=e,this.isSaving||this.saveTimeout?this.saveTimeout&&this.scheduleSave():this.executeSave()}))}scheduleSave(){this.saveTimeout&&clearTimeout(this.saveTimeout),this.saveTimeout=setTimeout((()=>{this.saveTimeout=void 0,this.executeSave()}),this.delayMs)}async executeSave(){if(this.isSaving)return;const e=this.nextSaveTask;if(!e)return;const s=this.pendingResolvers;this.pendingResolvers=[],this.nextSaveTask=void 0,this.isSaving=!0;try{const i=await e();s.forEach((({resolve:e})=>e(i)))}catch(e){s.forEach((({reject:s})=>s(e)))}finally{this.isSaving=!1,this.pendingResolvers.length>0&&this.scheduleSave()}}destroy(){this.saveTimeout&&(clearTimeout(this.saveTimeout),this.saveTimeout=void 0),this.pendingResolvers=[],this.nextSaveTask=void 0,this.isSaving=!1}}export{e as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"path";import e
|
|
1
|
+
import t from"path";import{getFormatExtension as s,resolveCodec as e}from"./format/index.js";let o=null;function a(a){const n=this.getOptions(),r=this.async(),i=s(n.messages.format);(async function(t,s){return o||(o=await e(t.messages.format,s)),o})(n,this.rootContext).then((s=>{const e=t.basename(this.resourcePath,i),o=s.toJSONString(a,{locale:e}),n=`export default JSON.parse(${JSON.stringify(o)});`;r(null,n)})).catch(r)}export{a as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"./ExtractionCompiler.js";async function
|
|
1
|
+
import t from"./ExtractionCompiler.js";import o from"./extractor/MessageExtractor.js";import{getDefaultProjectRoot as r}from"./utils.js";async function e(e){const a=new t(e,{extractor:new o({isDevelopment:!1,projectRoot:r()})});await a.extractAll()}export{e as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import t from"./ExtractionCompiler.js";import e from"./extractor/MessageExtractor.js";let o,r,s;function c(c){const a=this.getOptions(),i=this.async(),n=this.rootContext,p="development"===process.env["NODE_ENV".trim()];r||(r=new e({isDevelopment:p,projectRoot:n,sourceMap:this.sourceMap})),o||(o=new t(a,{isDevelopment:p,projectRoot:n,sourceMap:this.sourceMap,extractor:r})),s||(s=o.extractAll()),r.extract(this.resourcePath,c).then((async t=>{p||await s,i(null,t.code,t.map)})).catch(i)}export{c as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire as e}from"module";import t from"path";import{transform as s}from"@swc/core";import o from"./LRUCache.js";const
|
|
1
|
+
import{createRequire as e}from"module";import t from"path";import{transform as s}from"@swc/core";import{getDefaultProjectRoot as o}from"../utils.js";import r from"./LRUCache.js";const i=e(import.meta.url);class c{compileCache=(()=>new r(750))();constructor(e){this.isDevelopment=e.isDevelopment??!1,this.projectRoot=e.projectRoot??o(),this.sourceMap=e.sourceMap??!1}async extract(e,o){const r=[o,e].join("!"),c=this.compileCache.get(r);if(c)return c;if(!o.includes("useExtracted")&&!o.includes("getExtracted"))return{messages:[],code:o};const a=t.relative(this.projectRoot,e),p=await s(o,{jsc:{target:"esnext",parser:{syntax:"typescript",tsx:!0,decorators:!0},experimental:{cacheRoot:"node_modules/.cache/swc",disableBuiltinTransformsForInternalTesting:!0,disableAllLints:!0,plugins:[[i.resolve("next-intl-swc-plugin-extractor"),{isDevelopment:this.isDevelopment,filePath:a}]]}},sourceMaps:this.sourceMap,sourceFileName:a,filename:a}),l=p.output,n=JSON.parse(JSON.parse(l).results),m={code:p.code,map:p.map,messages:n};return this.compileCache.set(r,m),m}}export{c as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function n(n){return n}export{n as defineCodec};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getSortedMessages as o,setNestedProperty as t}from"../../utils.js";import{defineCodec as e}from"../ExtractorCodec.js";var r=e((()=>({decode(o){const t=JSON.parse(o),e=[];return s(t,((o,t)=>{e.push({id:t,message:o})})),e},encode(e){const r={};for(const s of o(e))t(r,s.id,s.message);return JSON.stringify(r,null,2)+"\n"},toJSONString:o=>o})));function s(o,t,e=""){for(const r of Object.keys(o)){const n=e?e+"."+r:r,c=o[r];"string"==typeof c?t(c,n):"object"==typeof c&&s(c,t,n)}}export{r as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import e from"po-parser";import{setNestedProperty as t,getSortedMessages as s}from"../../utils.js";import{defineCodec as r}from"../ExtractorCodec.js";var n=r((()=>{const r={"Content-Type":"text/plain; charset=utf-8","Content-Transfer-Encoding":"8bit","X-Generator":"next-intl","X-Crowdin-SourceKey":"msgstr"},n=".",o=new Map;return{decode(t,s){const r=e.parse(t);r.meta&&o.set(s.locale,r.meta);return(r.messages||[]).map((e=>{const{extractedComments:t,msgctxt:s,msgid:r,msgstr:o,...a}=e;if(t&&t.length>1)throw new Error(`Multiple extracted comments are not supported. Found ${t.length} comments for msgid "${r}".`);return{...a,id:s?[s,r].join(n):r,message:o,...t&&t.length>0&&{description:t[0]}}}))},encode(t,a){const m=s(t).map((e=>{const{description:t,id:s,message:r,...o}=e,a=s.lastIndexOf(n),m=s.includes(n);return{msgid:m?s.slice(a+1):s,msgstr:r,...t&&{extractedComments:[t]},...m&&{msgctxt:s.slice(0,a)},...o}}));return e.serialize({meta:{Language:a.locale,...r,...o.get(a.locale)},messages:m})},toJSONString(e,s){const r=this.decode(e,s),n={};for(const e of r)t(n,e.id,e.message);return JSON.stringify(n)}}}));export{n as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import o from"path";import{throwError as e}from"../../plugin/utils.js";const t={json:{codec:()=>import("./codecs/JSONCodec.js"),extension:".json"},po:{codec:()=>import("./codecs/POCodec.js"),extension:".po"}};function n(o){return"string"==typeof o&&o in t}function c(o){return n(o)?t[o].extension:o.extension}async function r(c,r){if(n(c)){return(0,(await t[c].codec()).default)()}{const t=o.isAbsolute(c.codec)?c.codec:o.resolve(r,c.codec);let n;try{n=await import(t)}catch(o){e(`Could not load codec from "${t}".\n${o}`)}const i=n.default;return i&&"function"==typeof i||e(`Codec at "${t}" must have a default export returned from \`defineCodec\`.`),i()}}export{t as default,c as getFormatExtension,r as resolveCodec};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"fs/promises";import i from"path";import r from"./SourceFileFilter.js";class t{static async walkSourceFiles(o,s,a=[]){const
|
|
1
|
+
import e from"fs/promises";import i from"path";import r from"./SourceFileFilter.js";class t{static async walkSourceFiles(o,s,a=[]){const c=await e.readdir(o,{withFileTypes:!0});for(const e of c){const c=i.join(o,e.name);if(e.isDirectory()){if(!r.shouldEnterDirectory(c,s))continue;await t.walkSourceFiles(c,s,a)}else r.isSourceFile(e.name)&&a.push(c)}return a}static async getSourceFiles(e){const i=(await Promise.all(e.map((i=>t.walkSourceFiles(i,e))))).flat();return new Set(i)}}export{t as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{subscribe as s}from"@parcel/watcher";import t from"./SourceFileFilter.js";class o{subscriptions=[];constructor(s,t){this.roots=s,this.onChange=t}async start(){if(this.subscriptions.length>0)return;const o=t.IGNORED_DIRECTORIES.map((s=>`**/${s}/**`));for(const i of this.roots){const r=await s(i,((s,o)=>{if(s)return void console.error(s);const i=o.filter((s=>t.isSourceFile(s.path)));i.length>0&&this.onChange(i)}),{ignore:o});this.subscriptions.push(r)}}async stop(){await Promise.all(this.subscriptions.map((s=>s.unsubscribe()))),this.subscriptions=[]}[Symbol.dispose](){this.stop()}}export{o as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
1
|
+
function e(e,t,n){const r=t.split(".");let o=e;for(let e=0;e<r.length-1;e++){const t=r[e];t in o&&"object"==typeof o[t]&&null!==o[t]||(o[t]={}),o=o[t]}o[r[r.length-1]]=n}function t(e){return e.toSorted(((e,t)=>{const r=e.references?.[0]?.path??"",o=t.references?.[0]?.path??"";return r===o?n(e.id,t.id):n(r,o)}))}function n(e,t){return e.localeCompare(t,"en")}function r(){return process.cwd()}export{r as getDefaultProjectRoot,t as getSortedMessages,n as localeCompare,e as setNestedProperty};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{default as unstable_extractMessages}from"./extractor/extractMessages.js";
|
|
1
|
+
export{default as unstable_extractMessages}from"./extractor/extractMessages.js";export{defineCodec}from"./extractor/format/ExtractorCodec.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"./getNextConfig.js";import{warn as t}from"./utils.js";import
|
|
1
|
+
import e from"./getNextConfig.js";import{warn as t}from"./utils.js";import r from"./declaration/createMessagesDeclaration.js";function o(o={}){const n="string"==typeof o?{requestConfig:o}:o;return function(o){return function(o,n){null!=n?.i18n&&t("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");const i=o.experimental?.createMessagesDeclaration;return i&&r("string"==typeof i?[i]:i),e(o,n)}(n,o)}}export{o as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"fs";import t from"path";import r from"../extractor/source/SourceFileFilter.js";import{isNextJs16OrHigher as
|
|
1
|
+
import e from"fs";import t from"path";import{getFormatExtension as r}from"../extractor/format/index.js";import s from"../extractor/source/SourceFileFilter.js";import{isNextJs16OrHigher as n,hasStableTurboConfig as o}from"./nextFlags.js";import{throwError as a}from"./utils.js";function i(e){return[`${e}.ts`,`${e}.tsx`,`${e}.js`,`${e}.jsx`]}function l(r,s){function n(r){return e.existsSync(function(e){const r=[];return s&&r.push(s),r.push(e),t.resolve(...r)}(r))}if(r)return n(r)||a(`Could not find i18n config at ${r}, please provide a valid path.`),r;for(const e of[...i("./i18n/request"),...i("./src/i18n/request")])if(n(e))return e;a("Could not locate request configuration module.\n\nThis path is supported by default: ./(src/)i18n/request.{js,jsx,ts,tsx}\n\nAlternatively, you can specify a custom location in your Next.js config:\n\nconst withNextIntl = createNextIntlPlugin(\n\nAlternatively, you can specify a custom location in your Next.js config:\n\nconst withNextIntl = createNextIntlPlugin(\n './path/to/i18n/request.tsx'\n);")}function u(e,i){const u={};function c(){const t=e.experimental;return t.srcPath&&e.experimental?.messages||a("`srcPath` and `messages` are required when using `extractor`."),{loader:"next-intl/extractor/extractionLoader",options:{srcPath:t.srcPath,sourceLocale:t.extract.sourceLocale,messages:e.experimental.messages}}}function p(){return{loader:"next-intl/extractor/catalogLoader",options:{messages:e.experimental.messages}}}function m(){return i?.turbopack?.rules||i?.experimental?.turbo?.rules||{}}function x(e,t,r){e[t]?Array.isArray(e[t])?e[t].push(r):e[t]=[e[t],r]:e[t]=r}if(null!=process.env.TURBOPACK){e.requestConfig&&t.isAbsolute(e.requestConfig)&&a("Turbopack support for next-intl currently does not support absolute paths, please provide a relative one (e.g. './src/i18n/config.ts').\n\nFound: "+e.requestConfig);const f={"next-intl/config":l(e.requestConfig)};let g;if(e.experimental?.extract){n()||a("Message extraction requires Next.js 16 or higher."),g??=m();const t=(Array.isArray(e.experimental.srcPath)?e.experimental.srcPath:[e.experimental.srcPath]).map((e=>e.endsWith("/")?e.slice(0,-1):e));x(g,`*.{${s.EXTENSIONS.join(",")}}`,{loaders:[c()],condition:{path:`{${t.join(",")}}/**/*`,content:/(useExtracted|getExtracted)/}})}if(e.experimental?.messages){n()||a("Message catalog loading requires Next.js 16 or higher."),g??=m();x(g,`*${r(e.experimental.messages.format)}`,{loaders:[p()],condition:{path:`${e.experimental.messages.path}/**/*`},as:"*.js"})}o()&&!i?.experimental?.turbo?u.turbopack={...i?.turbopack,...g&&{rules:g},resolveAlias:{...i?.turbopack?.resolveAlias,...f}}:u.experimental={...i?.experimental,turbo:{...i?.experimental?.turbo,...g&&{rules:g},resolveAlias:{...i?.experimental?.turbo?.resolveAlias,...f}}}}else u.webpack=function(n,o){if(n.resolve||(n.resolve={}),n.resolve.alias||(n.resolve.alias={}),n.resolve.alias["next-intl/config"]=t.resolve(n.context,l(e.requestConfig,n.context)),e.experimental?.extract){n.module||(n.module={}),n.module.rules||(n.module.rules=[]);const r=e.experimental.srcPath;n.module.rules.push({test:new RegExp(`\\.(${s.EXTENSIONS.join("|")})$`),include:Array.isArray(r)?r.map((e=>t.resolve(n.context,e))):t.resolve(n.context,r||""),use:[c()]})}if(e.experimental?.messages){n.module||(n.module={}),n.module.rules||(n.module.rules=[]);const s=r(e.experimental.messages.format);n.module.rules.push({test:new RegExp(`${s.replace(/\./g,"\\.")}$`),include:t.resolve(n.context,e.experimental.messages.path),use:[p()],type:"javascript/auto"})}return"function"==typeof i?.webpack?i.webpack(n,o):n};return i?.trailingSlash&&(u.env={...i.env,_next_intl_trailing_slash:"true"}),Object.assign({},i,u)}export{u as default};
|
|
@@ -1,20 +1,15 @@
|
|
|
1
|
+
import MessageExtractor from './extractor/MessageExtractor.js';
|
|
1
2
|
import type { ExtractorConfig } from './types.js';
|
|
2
3
|
export default class ExtractionCompiler implements Disposable {
|
|
3
4
|
private manager;
|
|
4
|
-
private isDevelopment;
|
|
5
|
-
private initialScanPromise;
|
|
6
5
|
constructor(config: ExtractorConfig, opts?: {
|
|
7
6
|
isDevelopment?: boolean;
|
|
8
7
|
projectRoot?: string;
|
|
9
8
|
sourceMap?: boolean;
|
|
9
|
+
extractor?: MessageExtractor;
|
|
10
10
|
});
|
|
11
|
-
|
|
12
|
-
messages: Array<import("./types.js").ExtractedMessage>;
|
|
13
|
-
code: string;
|
|
14
|
-
changed: boolean;
|
|
15
|
-
map?: string;
|
|
16
|
-
}>;
|
|
17
|
-
private performInitialScan;
|
|
18
|
-
extract(): Promise<void>;
|
|
11
|
+
extractAll(): Promise<void>;
|
|
19
12
|
[Symbol.dispose](): void;
|
|
13
|
+
private installExitHandlers;
|
|
14
|
+
private uninstallExitHandlers;
|
|
20
15
|
}
|
|
@@ -15,7 +15,6 @@ export default class CatalogLocales {
|
|
|
15
15
|
private sourceLocale;
|
|
16
16
|
private locales;
|
|
17
17
|
private watcher?;
|
|
18
|
-
private cleanupHandlers;
|
|
19
18
|
private targetLocales?;
|
|
20
19
|
private onChangeCallbacks;
|
|
21
20
|
constructor(params: CatalogLocalesParams);
|
|
@@ -26,6 +25,5 @@ export default class CatalogLocales {
|
|
|
26
25
|
private startWatcher;
|
|
27
26
|
private stopWatcher;
|
|
28
27
|
private onChange;
|
|
29
|
-
private setupCleanupHandlers;
|
|
30
28
|
}
|
|
31
29
|
export {};
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type MessageExtractor from '../extractor/MessageExtractor.js';
|
|
2
|
+
import type { ExtractorConfig } from '../types.js';
|
|
2
3
|
export default class CatalogManager {
|
|
3
4
|
private config;
|
|
5
|
+
/**
|
|
6
|
+
* The source of truth for which messages are used.
|
|
7
|
+
* NOTE: Should be mutated in place to keep `messagesById` and `messagesByFile` in sync.
|
|
8
|
+
*/
|
|
4
9
|
private messagesByFile;
|
|
10
|
+
/**
|
|
11
|
+
* Fast lookup for messages by ID across all files,
|
|
12
|
+
* contains the same messages as `messagesByFile`.
|
|
13
|
+
* NOTE: Should be mutated in place to keep `messagesById` and `messagesByFile` in sync.
|
|
14
|
+
*/
|
|
5
15
|
private messagesById;
|
|
6
16
|
/**
|
|
7
17
|
* This potentially also includes outdated ones that were initially available,
|
|
@@ -13,16 +23,18 @@ export default class CatalogManager {
|
|
|
13
23
|
private projectRoot;
|
|
14
24
|
private isDevelopment;
|
|
15
25
|
private persister?;
|
|
16
|
-
private
|
|
26
|
+
private codec?;
|
|
17
27
|
private catalogLocales?;
|
|
18
|
-
private
|
|
28
|
+
private extractor;
|
|
29
|
+
private sourceWatcher?;
|
|
19
30
|
loadCatalogsPromise?: Promise<unknown>;
|
|
20
|
-
constructor(config: ExtractorConfig, opts
|
|
31
|
+
constructor(config: ExtractorConfig, opts: {
|
|
21
32
|
projectRoot?: string;
|
|
22
33
|
isDevelopment?: boolean;
|
|
23
34
|
sourceMap?: boolean;
|
|
35
|
+
extractor: MessageExtractor;
|
|
24
36
|
});
|
|
25
|
-
private
|
|
37
|
+
private getCodec;
|
|
26
38
|
private getPersister;
|
|
27
39
|
private getCatalogLocales;
|
|
28
40
|
private getTargetLocales;
|
|
@@ -32,17 +44,15 @@ export default class CatalogManager {
|
|
|
32
44
|
private loadLocaleMessages;
|
|
33
45
|
private loadTargetMessages;
|
|
34
46
|
private reloadLocaleCatalog;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
changed: boolean;
|
|
39
|
-
map?: string;
|
|
40
|
-
}>;
|
|
47
|
+
private mergeSourceDiskMetadata;
|
|
48
|
+
processFile(absoluteFilePath: string): Promise<boolean>;
|
|
49
|
+
private mergeReferences;
|
|
41
50
|
private haveMessagesChangedForFile;
|
|
42
51
|
private areMessagesEqual;
|
|
43
52
|
save(): Promise<void>;
|
|
44
53
|
private saveImpl;
|
|
45
54
|
private saveLocale;
|
|
46
55
|
private onLocalesChange;
|
|
56
|
+
private handleFileEvents;
|
|
47
57
|
destroy(): void;
|
|
48
58
|
}
|
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type {
|
|
1
|
+
import type ExtractorCodec from '../format/ExtractorCodec.js';
|
|
2
|
+
import type { ExtractorMessage, Locale } from '../types.js';
|
|
3
3
|
export default class CatalogPersister {
|
|
4
4
|
private messagesPath;
|
|
5
|
-
private
|
|
6
|
-
|
|
5
|
+
private codec;
|
|
6
|
+
private extension;
|
|
7
|
+
constructor(params: {
|
|
8
|
+
messagesPath: string;
|
|
9
|
+
codec: ExtractorCodec;
|
|
10
|
+
extension: string;
|
|
11
|
+
});
|
|
12
|
+
private getFileName;
|
|
7
13
|
private getFilePath;
|
|
8
|
-
read(locale: Locale): Promise<Array<
|
|
9
|
-
write(
|
|
14
|
+
read(locale: Locale): Promise<Array<ExtractorMessage>>;
|
|
15
|
+
write(messages: Array<ExtractorMessage>, context: {
|
|
16
|
+
locale: Locale;
|
|
17
|
+
sourceMessagesById: Map<string, ExtractorMessage>;
|
|
18
|
+
}): Promise<void>;
|
|
10
19
|
getLastModified(locale: Locale): Promise<Date | undefined>;
|
|
11
20
|
}
|