next-intl 4.5.8 → 4.6.1
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-D9Tw618d.cjs +7 -0
- package/dist/cjs/development/JSONCodec-L1_VeQBi.cjs +48 -0
- package/dist/cjs/development/POCodec-Be_UL6jy.cjs +105 -0
- package/dist/cjs/development/plugin-DDtWCyPI.cjs +1373 -0
- package/dist/cjs/development/plugin.cjs +8 -379
- package/dist/esm/development/extractor/ExtractionCompiler.js +23 -26
- package/dist/esm/development/extractor/catalog/CatalogLocales.js +0 -33
- package/dist/esm/development/extractor/catalog/CatalogManager.js +171 -110
- package/dist/esm/development/extractor/catalog/CatalogPersister.js +31 -13
- package/dist/esm/development/extractor/catalog/SaveScheduler.js +1 -1
- 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 +15 -12
- 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 +132 -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 +3 -1
- package/dist/esm/development/plugin/declaration/createMessagesDeclaration.js +2 -11
- package/dist/esm/development/plugin/extractor/initExtractionCompiler.js +45 -0
- package/dist/esm/development/plugin/getNextConfig.js +7 -4
- package/dist/esm/development/plugin/utils.js +16 -1
- 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/declaration/createMessagesDeclaration.js +1 -1
- package/dist/esm/production/plugin/extractor/initExtractionCompiler.js +1 -0
- package/dist/esm/production/plugin/getNextConfig.js +1 -1
- package/dist/esm/production/plugin/utils.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 +26 -15
- package/dist/types/extractor/catalog/CatalogPersister.d.ts +15 -6
- package/dist/types/extractor/catalog/SaveScheduler.d.ts +2 -2
- 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 +2 -2
- package/dist/types/extractor/source/SourceFileScanner.d.ts +1 -1
- package/dist/types/extractor/source/SourceFileWatcher.d.ts +15 -0
- package/dist/types/extractor/types.d.ts +2 -2
- package/dist/types/extractor/utils.d.ts +3 -0
- package/dist/types/plugin/extractor/initExtractionCompiler.d.ts +2 -0
- package/dist/types/plugin/types.d.ts +1 -1
- package/dist/types/plugin/utils.d.ts +6 -0
- 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/extractor/ASTScope.d.ts +0 -12
- 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
|
@@ -1,384 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
var plugin = require('./plugin-DDtWCyPI.cjs');
|
|
4
|
+
require('fs/promises');
|
|
5
|
+
require('path');
|
|
6
|
+
require('@parcel/watcher');
|
|
7
|
+
require('fs');
|
|
8
|
+
require('module');
|
|
9
|
+
require('@swc/core');
|
|
6
10
|
|
|
7
|
-
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
8
|
-
function formatMessage(message) {
|
|
9
|
-
return `\n[next-intl] ${message}\n`;
|
|
10
|
-
}
|
|
11
|
-
function throwError(message) {
|
|
12
|
-
throw new Error(formatMessage(message));
|
|
13
|
-
}
|
|
14
|
-
function warn(message) {
|
|
15
|
-
console.warn(formatMessage(message));
|
|
16
|
-
}
|
|
17
11
|
|
|
18
|
-
/**
|
|
19
|
-
* Wrapper around `fs.watch` that provides a workaround
|
|
20
|
-
* for https://github.com/nodejs/node/issues/5039.
|
|
21
|
-
*/
|
|
22
|
-
function watchFile(filepath, callback) {
|
|
23
|
-
const directory = path.dirname(filepath);
|
|
24
|
-
const filename = path.basename(filepath);
|
|
25
|
-
return fs.watch(directory, {
|
|
26
|
-
persistent: false,
|
|
27
|
-
recursive: false
|
|
28
|
-
}, (event, changedFilename) => {
|
|
29
|
-
if (changedFilename === filename) {
|
|
30
|
-
callback();
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
12
|
|
|
35
|
-
|
|
36
|
-
if (process.env._NEXT_INTL_COMPILE_MESSAGES === '1') {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
process.env._NEXT_INTL_COMPILE_MESSAGES = '1';
|
|
40
|
-
fn();
|
|
41
|
-
}
|
|
42
|
-
function createMessagesDeclaration(messagesPaths) {
|
|
43
|
-
// Instead of running _only_ in certain cases, it's
|
|
44
|
-
// safer to _avoid_ running for certain known cases.
|
|
45
|
-
// https://github.com/amannn/next-intl/issues/2006
|
|
46
|
-
const shouldBailOut = ['info', 'start'
|
|
47
|
-
|
|
48
|
-
// Note: These commands don't consult the
|
|
49
|
-
// Next.js config, so we can't detect them here.
|
|
50
|
-
// - telemetry
|
|
51
|
-
// - lint
|
|
52
|
-
//
|
|
53
|
-
// What remains are:
|
|
54
|
-
// - dev
|
|
55
|
-
// - build
|
|
56
|
-
// - typegen
|
|
57
|
-
].some(arg => process.argv.includes(arg));
|
|
58
|
-
if (shouldBailOut) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Next.js can call the Next.js config multiple
|
|
63
|
-
// times - ensure we only run once.
|
|
64
|
-
runOnce(() => {
|
|
65
|
-
for (const messagesPath of messagesPaths) {
|
|
66
|
-
const fullPath = path.resolve(messagesPath);
|
|
67
|
-
if (!fs.existsSync(fullPath)) {
|
|
68
|
-
throwError(`\`createMessagesDeclaration\` points to a non-existent file: ${fullPath}`);
|
|
69
|
-
}
|
|
70
|
-
if (!fullPath.endsWith('.json')) {
|
|
71
|
-
throwError(`\`createMessagesDeclaration\` needs to point to a JSON file. Received: ${fullPath}`);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Keep this as a runtime check and don't replace
|
|
75
|
-
// this with a constant during the build process
|
|
76
|
-
const env = process.env['NODE_ENV'.trim()];
|
|
77
|
-
compileDeclaration(messagesPath);
|
|
78
|
-
if (env === 'development') {
|
|
79
|
-
startWatching(messagesPath);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
function startWatching(messagesPath) {
|
|
85
|
-
const watcher = watchFile(messagesPath, () => {
|
|
86
|
-
compileDeclaration(messagesPath, true);
|
|
87
|
-
});
|
|
88
|
-
process.on('exit', () => {
|
|
89
|
-
watcher.close();
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
function compileDeclaration(messagesPath, async = false) {
|
|
93
|
-
const declarationPath = messagesPath.replace(/\.json$/, '.d.json.ts');
|
|
94
|
-
function createDeclaration(content) {
|
|
95
|
-
return `// This file is auto-generated by next-intl, do not edit directly.
|
|
96
|
-
// See: https://next-intl.dev/docs/workflows/typescript#messages-arguments
|
|
97
|
-
|
|
98
|
-
declare const messages: ${content.trim()};
|
|
99
|
-
export default messages;`;
|
|
100
|
-
}
|
|
101
|
-
if (async) {
|
|
102
|
-
return fs.promises.readFile(messagesPath, 'utf-8').then(content => fs.promises.writeFile(declarationPath, createDeclaration(content)));
|
|
103
|
-
}
|
|
104
|
-
const content = fs.readFileSync(messagesPath, 'utf-8');
|
|
105
|
-
fs.writeFileSync(declarationPath, createDeclaration(content));
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
class SourceFileFilter {
|
|
109
|
-
static EXTENSIONS = ['ts', 'tsx', 'js', 'jsx'];
|
|
110
|
-
|
|
111
|
-
// Will not be entered, except if explicitly asked for
|
|
112
|
-
// TODO: At some point we should infer these from .gitignore
|
|
113
|
-
static IGNORED_DIRECTORIES = ['node_modules', '.next', '.git'];
|
|
114
|
-
static isSourceFile(filePath) {
|
|
115
|
-
const ext = path.extname(filePath);
|
|
116
|
-
return SourceFileFilter.EXTENSIONS.map(cur => '.' + cur).includes(ext);
|
|
117
|
-
}
|
|
118
|
-
static shouldEnterDirectory(dirPath, srcPaths) {
|
|
119
|
-
const dirName = path.basename(dirPath);
|
|
120
|
-
if (SourceFileFilter.IGNORED_DIRECTORIES.includes(dirName)) {
|
|
121
|
-
return SourceFileFilter.isIgnoredDirectoryExplicitlyIncluded(dirPath, srcPaths);
|
|
122
|
-
}
|
|
123
|
-
return true;
|
|
124
|
-
}
|
|
125
|
-
static isIgnoredDirectoryExplicitlyIncluded(ignoredDirPath, srcPaths) {
|
|
126
|
-
return srcPaths.some(srcPath => SourceFileFilter.isWithinPath(srcPath, ignoredDirPath));
|
|
127
|
-
}
|
|
128
|
-
static isWithinPath(targetPath, basePath) {
|
|
129
|
-
const relativePath = path.relative(basePath, targetPath);
|
|
130
|
-
return relativePath === '' || !relativePath.startsWith('..');
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function getCurrentVersion() {
|
|
135
|
-
try {
|
|
136
|
-
const require$1 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('plugin.cjs', document.baseURI).href)));
|
|
137
|
-
const pkg = require$1('next/package.json');
|
|
138
|
-
return pkg.version;
|
|
139
|
-
} catch (error) {
|
|
140
|
-
throw new Error('Failed to get current Next.js version. This can happen if next-intl/plugin is imported into your app code outside of your next.config.js.', {
|
|
141
|
-
cause: error
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
function compareVersions(version1, version2) {
|
|
146
|
-
const v1Parts = version1.split('.').map(Number);
|
|
147
|
-
const v2Parts = version2.split('.').map(Number);
|
|
148
|
-
for (let i = 0; i < 3; i++) {
|
|
149
|
-
const v1 = v1Parts[i] || 0;
|
|
150
|
-
const v2 = v2Parts[i] || 0;
|
|
151
|
-
if (v1 > v2) return 1;
|
|
152
|
-
if (v1 < v2) return -1;
|
|
153
|
-
}
|
|
154
|
-
return 0;
|
|
155
|
-
}
|
|
156
|
-
function hasStableTurboConfig() {
|
|
157
|
-
return compareVersions(getCurrentVersion(), '15.3.0') >= 0;
|
|
158
|
-
}
|
|
159
|
-
function isNextJs16OrHigher() {
|
|
160
|
-
return compareVersions(getCurrentVersion(), '16.0.0') >= 0;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function withExtensions(localPath) {
|
|
164
|
-
return [`${localPath}.ts`, `${localPath}.tsx`, `${localPath}.js`, `${localPath}.jsx`];
|
|
165
|
-
}
|
|
166
|
-
function resolveI18nPath(providedPath, cwd) {
|
|
167
|
-
function resolvePath(pathname) {
|
|
168
|
-
const parts = [];
|
|
169
|
-
if (cwd) parts.push(cwd);
|
|
170
|
-
parts.push(pathname);
|
|
171
|
-
return path.resolve(...parts);
|
|
172
|
-
}
|
|
173
|
-
function pathExists(pathname) {
|
|
174
|
-
return fs.existsSync(resolvePath(pathname));
|
|
175
|
-
}
|
|
176
|
-
if (providedPath) {
|
|
177
|
-
if (!pathExists(providedPath)) {
|
|
178
|
-
throwError(`Could not find i18n config at ${providedPath}, please provide a valid path.`);
|
|
179
|
-
}
|
|
180
|
-
return providedPath;
|
|
181
|
-
} else {
|
|
182
|
-
for (const candidate of [...withExtensions('./i18n/request'), ...withExtensions('./src/i18n/request')]) {
|
|
183
|
-
if (pathExists(candidate)) {
|
|
184
|
-
return candidate;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
throwError(`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(
|
|
188
|
-
|
|
189
|
-
Alternatively, you can specify a custom location in your Next.js config:
|
|
190
|
-
|
|
191
|
-
const withNextIntl = createNextIntlPlugin(
|
|
192
|
-
'./path/to/i18n/request.tsx'
|
|
193
|
-
);`);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
function getNextConfig(pluginConfig, nextConfig) {
|
|
197
|
-
const useTurbo = process.env.TURBOPACK != null;
|
|
198
|
-
const nextIntlConfig = {};
|
|
199
|
-
function getExtractMessagesLoaderConfig() {
|
|
200
|
-
const experimental = pluginConfig.experimental;
|
|
201
|
-
if (!experimental.srcPath || !experimental.messages) {
|
|
202
|
-
throwError('`srcPath` and `messages` are required when using `extractor`.');
|
|
203
|
-
}
|
|
204
|
-
return {
|
|
205
|
-
loader: 'next-intl/extractor/extractionLoader',
|
|
206
|
-
options: {
|
|
207
|
-
srcPath: experimental.srcPath,
|
|
208
|
-
sourceLocale: experimental.extract.sourceLocale,
|
|
209
|
-
messages: experimental.messages
|
|
210
|
-
}
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
function getCatalogLoaderConfig() {
|
|
214
|
-
return {
|
|
215
|
-
loader: 'next-intl/extractor/catalogLoader',
|
|
216
|
-
options: {
|
|
217
|
-
messages: pluginConfig.experimental.messages
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
function getTurboRules() {
|
|
222
|
-
return nextConfig?.turbopack?.rules ||
|
|
223
|
-
// @ts-expect-error -- For Next.js <16
|
|
224
|
-
nextConfig?.experimental?.turbo?.rules || {};
|
|
225
|
-
}
|
|
226
|
-
function addTurboRule(rules, glob, rule) {
|
|
227
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
228
|
-
if (rules[glob]) {
|
|
229
|
-
if (Array.isArray(rules[glob])) {
|
|
230
|
-
rules[glob].push(rule);
|
|
231
|
-
} else {
|
|
232
|
-
rules[glob] = [rules[glob], rule];
|
|
233
|
-
}
|
|
234
|
-
} else {
|
|
235
|
-
rules[glob] = rule;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
if (useTurbo) {
|
|
239
|
-
if (pluginConfig.requestConfig && path.isAbsolute(pluginConfig.requestConfig)) {
|
|
240
|
-
throwError("Turbopack support for next-intl currently does not support absolute paths, please provide a relative one (e.g. './src/i18n/config.ts').\n\nFound: " + pluginConfig.requestConfig);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Assign alias for `next-intl/config`
|
|
244
|
-
const resolveAlias = {
|
|
245
|
-
// Turbo aliases don't work with absolute
|
|
246
|
-
// paths (see error handling above)
|
|
247
|
-
'next-intl/config': resolveI18nPath(pluginConfig.requestConfig)
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
// Add loaders
|
|
251
|
-
let rules;
|
|
252
|
-
|
|
253
|
-
// Add loader for extractor
|
|
254
|
-
if (pluginConfig.experimental?.extract) {
|
|
255
|
-
if (!isNextJs16OrHigher()) {
|
|
256
|
-
throwError('Message extraction requires Next.js 16 or higher.');
|
|
257
|
-
}
|
|
258
|
-
rules ??= getTurboRules();
|
|
259
|
-
const srcPaths = (Array.isArray(pluginConfig.experimental.srcPath) ? pluginConfig.experimental.srcPath : [pluginConfig.experimental.srcPath]).map(srcPath => srcPath.endsWith('/') ? srcPath.slice(0, -1) : srcPath);
|
|
260
|
-
addTurboRule(rules, `*.{${SourceFileFilter.EXTENSIONS.join(',')}}`, {
|
|
261
|
-
loaders: [getExtractMessagesLoaderConfig()],
|
|
262
|
-
condition: {
|
|
263
|
-
// Note: We don't need `not: 'foreign'`, because this is
|
|
264
|
-
// implied by the filter based on `srcPath`.
|
|
265
|
-
path: `{${srcPaths.join(',')}}` + '/**/*',
|
|
266
|
-
content: /(useExtracted|getExtracted)/
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// Add loader for catalog
|
|
272
|
-
if (pluginConfig.experimental?.messages) {
|
|
273
|
-
if (!isNextJs16OrHigher()) {
|
|
274
|
-
throwError('Message catalog loading requires Next.js 16 or higher.');
|
|
275
|
-
}
|
|
276
|
-
rules ??= getTurboRules();
|
|
277
|
-
addTurboRule(rules, `*.${pluginConfig.experimental.messages.format}`, {
|
|
278
|
-
loaders: [getCatalogLoaderConfig()],
|
|
279
|
-
condition: {
|
|
280
|
-
path: `${pluginConfig.experimental.messages.path}/**/*`
|
|
281
|
-
},
|
|
282
|
-
as: '*.js'
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
if (hasStableTurboConfig() &&
|
|
286
|
-
// @ts-expect-error -- For Next.js <16
|
|
287
|
-
!nextConfig?.experimental?.turbo) {
|
|
288
|
-
nextIntlConfig.turbopack = {
|
|
289
|
-
...nextConfig?.turbopack,
|
|
290
|
-
...(rules && {
|
|
291
|
-
rules
|
|
292
|
-
}),
|
|
293
|
-
resolveAlias: {
|
|
294
|
-
...nextConfig?.turbopack?.resolveAlias,
|
|
295
|
-
...resolveAlias
|
|
296
|
-
}
|
|
297
|
-
};
|
|
298
|
-
} else {
|
|
299
|
-
nextIntlConfig.experimental = {
|
|
300
|
-
...nextConfig?.experimental,
|
|
301
|
-
// @ts-expect-error -- For Next.js <16
|
|
302
|
-
turbo: {
|
|
303
|
-
// @ts-expect-error -- For Next.js <16
|
|
304
|
-
...nextConfig?.experimental?.turbo,
|
|
305
|
-
...(rules && {
|
|
306
|
-
rules
|
|
307
|
-
}),
|
|
308
|
-
resolveAlias: {
|
|
309
|
-
// @ts-expect-error -- For Next.js <16
|
|
310
|
-
...nextConfig?.experimental?.turbo?.resolveAlias,
|
|
311
|
-
...resolveAlias
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
} else {
|
|
317
|
-
nextIntlConfig.webpack = function webpack(config, context) {
|
|
318
|
-
if (!config.resolve) config.resolve = {};
|
|
319
|
-
if (!config.resolve.alias) config.resolve.alias = {};
|
|
320
|
-
|
|
321
|
-
// Assign alias for `next-intl/config`
|
|
322
|
-
// (Webpack requires absolute paths)
|
|
323
|
-
config.resolve.alias['next-intl/config'] = path.resolve(config.context, resolveI18nPath(pluginConfig.requestConfig, config.context));
|
|
324
|
-
|
|
325
|
-
// Add loader for extractor
|
|
326
|
-
if (pluginConfig.experimental?.extract) {
|
|
327
|
-
if (!config.module) config.module = {};
|
|
328
|
-
if (!config.module.rules) config.module.rules = [];
|
|
329
|
-
const srcPath = pluginConfig.experimental.srcPath;
|
|
330
|
-
config.module.rules.push({
|
|
331
|
-
test: new RegExp(`\\.(${SourceFileFilter.EXTENSIONS.join('|')})$`),
|
|
332
|
-
include: Array.isArray(srcPath) ? srcPath.map(cur => path.resolve(config.context, cur)) : path.resolve(config.context, srcPath || ''),
|
|
333
|
-
use: [getExtractMessagesLoaderConfig()]
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
// Add loader for catalog
|
|
338
|
-
if (pluginConfig.experimental?.messages) {
|
|
339
|
-
if (!config.module) config.module = {};
|
|
340
|
-
if (!config.module.rules) config.module.rules = [];
|
|
341
|
-
config.module.rules.push({
|
|
342
|
-
test: new RegExp(`\\.${pluginConfig.experimental.messages.format}$`),
|
|
343
|
-
include: path.resolve(config.context, pluginConfig.experimental.messages.path),
|
|
344
|
-
use: [getCatalogLoaderConfig()],
|
|
345
|
-
type: 'javascript/auto'
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
if (typeof nextConfig?.webpack === 'function') {
|
|
349
|
-
return nextConfig.webpack(config, context);
|
|
350
|
-
}
|
|
351
|
-
return config;
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
// Forward config
|
|
356
|
-
if (nextConfig?.trailingSlash) {
|
|
357
|
-
nextIntlConfig.env = {
|
|
358
|
-
...nextConfig.env,
|
|
359
|
-
_next_intl_trailing_slash: 'true'
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
return Object.assign({}, nextConfig, nextIntlConfig);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
function initPlugin(pluginConfig, nextConfig) {
|
|
366
|
-
if (nextConfig?.i18n != null) {
|
|
367
|
-
warn("\n[next-intl] 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
|
-
}
|
|
369
|
-
const messagesPathOrPaths = pluginConfig.experimental?.createMessagesDeclaration;
|
|
370
|
-
if (messagesPathOrPaths) {
|
|
371
|
-
createMessagesDeclaration(typeof messagesPathOrPaths === 'string' ? [messagesPathOrPaths] : messagesPathOrPaths);
|
|
372
|
-
}
|
|
373
|
-
return getNextConfig(pluginConfig, nextConfig);
|
|
374
|
-
}
|
|
375
|
-
function createNextIntlPlugin(i18nPathOrConfig = {}) {
|
|
376
|
-
const config = typeof i18nPathOrConfig === 'string' ? {
|
|
377
|
-
requestConfig: i18nPathOrConfig
|
|
378
|
-
} : i18nPathOrConfig;
|
|
379
|
-
return function withNextIntl(nextConfig) {
|
|
380
|
-
return initPlugin(config, nextConfig);
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
module.exports = createNextIntlPlugin;
|
|
13
|
+
module.exports = plugin.createNextIntlPlugin;
|
|
@@ -1,40 +1,37 @@
|
|
|
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]() {
|
|
37
|
-
this.
|
|
21
|
+
this.uninstallExitHandlers();
|
|
22
|
+
this.manager[Symbol.dispose]();
|
|
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);
|
|
38
35
|
}
|
|
39
36
|
}
|
|
40
37
|
|
|
@@ -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 };
|