next-intl 4.5.0 → 4.5.2
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/plugin.cjs +20 -1
- package/dist/esm/development/extractor/catalog/CatalogManager.js +1 -0
- package/dist/esm/development/extractor/source/SourceFileFilter.js +18 -0
- package/dist/esm/development/extractor/source/SourceFileScanner.js +3 -0
- package/dist/esm/development/middleware/utils.js +6 -2
- package/dist/esm/development/plugin/getNextConfig.js +2 -1
- package/dist/esm/development/shared/utils.js +2 -1
- package/dist/esm/production/extractor/catalog/CatalogManager.js +1 -1
- package/dist/esm/production/extractor/source/SourceFileFilter.js +1 -1
- package/dist/esm/production/extractor/source/SourceFileScanner.js +1 -1
- package/dist/esm/production/middleware/utils.js +1 -1
- package/dist/esm/production/plugin/getNextConfig.js +1 -1
- package/dist/esm/production/shared/utils.js +1 -1
- package/dist/types/extractor/source/SourceFileFilter.d.ts +4 -0
- package/dist/types/extractor/types.d.ts +1 -1
- package/dist/types/plugin/types.d.ts +1 -1
- package/package.json +3 -3
|
@@ -107,10 +107,28 @@ export default messages;`;
|
|
|
107
107
|
|
|
108
108
|
class SourceFileFilter {
|
|
109
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'];
|
|
110
114
|
static isSourceFile(filePath) {
|
|
111
115
|
const ext = path.extname(filePath);
|
|
112
116
|
return SourceFileFilter.EXTENSIONS.map(cur => '.' + cur).includes(ext);
|
|
113
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
|
+
}
|
|
114
132
|
}
|
|
115
133
|
|
|
116
134
|
function getCurrentVersion() {
|
|
@@ -238,12 +256,13 @@ function getNextConfig(pluginConfig, nextConfig) {
|
|
|
238
256
|
throwError('Message extraction requires Next.js 16 or higher.');
|
|
239
257
|
}
|
|
240
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);
|
|
241
260
|
addTurboRule(rules, `*.{${SourceFileFilter.EXTENSIONS.join(',')}}`, {
|
|
242
261
|
loaders: [getExtractMessagesLoaderConfig()],
|
|
243
262
|
condition: {
|
|
244
263
|
// Note: We don't need `not: 'foreign'`, because this is
|
|
245
264
|
// implied by the filter based on `srcPath`.
|
|
246
|
-
path:
|
|
265
|
+
path: `{${srcPaths.join(',')}}` + '/**/*',
|
|
247
266
|
content: /(useExtracted|getExtracted)/
|
|
248
267
|
}
|
|
249
268
|
});
|
|
@@ -2,10 +2,28 @@ import path from 'path';
|
|
|
2
2
|
|
|
3
3
|
class SourceFileFilter {
|
|
4
4
|
static EXTENSIONS = ['ts', 'tsx', 'js', 'jsx'];
|
|
5
|
+
|
|
6
|
+
// Will not be entered, except if explicitly asked for
|
|
7
|
+
// TODO: At some point we should infer these from .gitignore
|
|
8
|
+
static IGNORED_DIRECTORIES = ['node_modules', '.next', '.git'];
|
|
5
9
|
static isSourceFile(filePath) {
|
|
6
10
|
const ext = path.extname(filePath);
|
|
7
11
|
return SourceFileFilter.EXTENSIONS.map(cur => '.' + cur).includes(ext);
|
|
8
12
|
}
|
|
13
|
+
static shouldEnterDirectory(dirPath, srcPaths) {
|
|
14
|
+
const dirName = path.basename(dirPath);
|
|
15
|
+
if (SourceFileFilter.IGNORED_DIRECTORIES.includes(dirName)) {
|
|
16
|
+
return SourceFileFilter.isIgnoredDirectoryExplicitlyIncluded(dirPath, srcPaths);
|
|
17
|
+
}
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
static isIgnoredDirectoryExplicitlyIncluded(ignoredDirPath, srcPaths) {
|
|
21
|
+
return srcPaths.some(srcPath => SourceFileFilter.isWithinPath(srcPath, ignoredDirPath));
|
|
22
|
+
}
|
|
23
|
+
static isWithinPath(targetPath, basePath) {
|
|
24
|
+
const relativePath = path.relative(basePath, targetPath);
|
|
25
|
+
return relativePath === '' || !relativePath.startsWith('..');
|
|
26
|
+
}
|
|
9
27
|
}
|
|
10
28
|
|
|
11
29
|
export { SourceFileFilter as default };
|
|
@@ -10,6 +10,9 @@ class SourceFileScanner {
|
|
|
10
10
|
for (const entry of entries) {
|
|
11
11
|
const entryPath = path.join(dir, entry.name);
|
|
12
12
|
if (entry.isDirectory()) {
|
|
13
|
+
if (!SourceFileFilter.shouldEnterDirectory(entryPath, srcPaths)) {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
13
16
|
await SourceFileScanner.walkSourceFiles(entryPath, srcPaths, acc);
|
|
14
17
|
} else {
|
|
15
18
|
if (SourceFileFilter.isSourceFile(entry.name)) {
|
|
@@ -121,9 +121,13 @@ function getRouteParams(template, pathname) {
|
|
|
121
121
|
const match = regex.exec(normalizedPathname);
|
|
122
122
|
if (!match) return undefined;
|
|
123
123
|
const params = {};
|
|
124
|
+
const keys = normalizedTemplate.match(/\[([^\]]+)\]/g) ?? [];
|
|
124
125
|
for (let i = 1; i < match.length; i++) {
|
|
125
|
-
const
|
|
126
|
-
if (
|
|
126
|
+
const rawKey = keys[i - 1];
|
|
127
|
+
if (!rawKey) continue;
|
|
128
|
+
const key = rawKey.replace(/[[\]]/g, '');
|
|
129
|
+
const value = match[i] ?? '';
|
|
130
|
+
params[key] = value;
|
|
127
131
|
}
|
|
128
132
|
return params;
|
|
129
133
|
}
|
|
@@ -100,12 +100,13 @@ function getNextConfig(pluginConfig, nextConfig) {
|
|
|
100
100
|
throwError('Message extraction requires Next.js 16 or higher.');
|
|
101
101
|
}
|
|
102
102
|
rules ??= getTurboRules();
|
|
103
|
+
const srcPaths = (Array.isArray(pluginConfig.experimental.srcPath) ? pluginConfig.experimental.srcPath : [pluginConfig.experimental.srcPath]).map(srcPath => srcPath.endsWith('/') ? srcPath.slice(0, -1) : srcPath);
|
|
103
104
|
addTurboRule(rules, `*.{${SourceFileFilter.EXTENSIONS.join(',')}}`, {
|
|
104
105
|
loaders: [getExtractMessagesLoaderConfig()],
|
|
105
106
|
condition: {
|
|
106
107
|
// Note: We don't need `not: 'foreign'`, because this is
|
|
107
108
|
// implied by the filter based on `srcPath`.
|
|
108
|
-
path:
|
|
109
|
+
path: `{${srcPaths.join(',')}}` + '/**/*',
|
|
109
110
|
content: /(useExtracted|getExtracted)/
|
|
110
111
|
}
|
|
111
112
|
});
|
|
@@ -78,7 +78,8 @@ function getLocaleAsPrefix(locale) {
|
|
|
78
78
|
function templateToRegex(template) {
|
|
79
79
|
const regexPattern = template
|
|
80
80
|
// Replace optional catchall ('[[...slug]]')
|
|
81
|
-
.replace(
|
|
81
|
+
.replace(/\/\[\[(\.\.\.[^\]]+)\]\]/g, '(?:/(.*))?') // With leading slash
|
|
82
|
+
.replace(/\[\[(\.\.\.[^\]]+)\]\]/g, '(?:/(.*))?') // Without leading slash
|
|
82
83
|
// Replace catchall ('[...slug]')
|
|
83
84
|
.replace(/\[(\.\.\.[^\]]+)\]/g, '(.+)')
|
|
84
85
|
// Replace regular parameter ('[slug]')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"fs/promises";import s from"path";import t from"../extractor/MessageExtractor.js";import a from"../formatters/index.js";import
|
|
1
|
+
import e from"fs/promises";import s from"path";import t from"../extractor/MessageExtractor.js";import a from"../formatters/index.js";import o from"../source/SourceFileScanner.js";import r from"./CatalogLocales.js";import i from"./CatalogPersister.js";import c from"./SaveScheduler.js";class n{messagesByFile=(()=>new Map)();messagesById=(()=>new Map)();translationsByTargetLocale=(()=>new Map)();lastWriteByLocale=(()=>new Map)();constructor(e,s={}){this.config=e,this.saveScheduler=new c(50),this.projectRoot=s.projectRoot||process.cwd(),this.isDevelopment=s.isDevelopment??!1,this.messageExtractor=new t({isDevelopment:this.isDevelopment,projectRoot:this.projectRoot})}async getFormatter(){if(this.formatter)return this.formatter;{const e=(await a[this.config.messages.format]()).default;return this.formatter=new e,this.formatter}}async getPersister(){return this.persister||(this.persister=new i(this.config.messages.path,await this.getFormatter())),this.persister}async getCatalogLocales(){if(this.catalogLocales)return this.catalogLocales;{const e=s.join(this.projectRoot,this.config.messages.path),t=await this.getFormatter();return this.catalogLocales=new r({messagesDir:e,sourceLocale:this.config.sourceLocale,extension:t.EXTENSION,locales:this.config.messages.locales}),this.catalogLocales}}async getTargetLocales(){return(await this.getCatalogLocales()).getTargetLocales()}getSrcPaths(){return(Array.isArray(this.config.srcPath)?this.config.srcPath:[this.config.srcPath]).map((e=>s.join(this.projectRoot,e)))}getFileMessages(e){return this.messagesByFile.get(e)}async loadMessages(){if(await this.loadSourceMessages(),await this.loadTargetMessages(),this.isDevelopment){(await this.getCatalogLocales()).subscribeLocalesChange(this.onLocalesChange)}}async loadSourceMessages(){await this.loadLocaleMessages(this.config.sourceLocale);const s=await o.getSourceFiles(this.getSrcPaths());await Promise.all(s.map((async s=>this.extractFileMessages(s,await e.readFile(s,"utf8")))))}async loadLocaleMessages(e){const s=await this.getPersister();try{const t=await s.read(e),a=await s.getLastModified(e);return this.lastWriteByLocale.set(e,a),t}catch{return[]}}async loadTargetMessages(){const e=await this.getTargetLocales();await Promise.all(e.map((async e=>{this.translationsByTargetLocale.set(e,new Map);const s=await this.loadLocaleMessages(e);for(const t of s){this.translationsByTargetLocale.get(e).set(t.id,t.message)}})))}async extractFileMessages(e,t){const a=await this.messageExtractor.processFileContent(e,t),o=this.messagesByFile.get(e),r=Array.from(o?.keys()??[]),i=new Map;for(let e of a.messages){const s=this.messagesById.get(e.id);if(s){const t=[...s.references??[]];e.references.forEach((e=>{t.some((s=>s.path===e.path))||t.push(e)})),t.sort(((e,s)=>e.path.localeCompare(s.path))),e={...e,references:t},s.description&&!e.description&&(e={...e,description:s.description})}this.messagesById.set(e.id,e),i.set(e.id,e);const t=r.indexOf(e.id);-1!==t&&r.splice(t,1)}const c=s.relative(this.projectRoot,e);r.filter((e=>{const s=this.messagesById.get(e);return!s?.references?.some((e=>e.path!==c))})).forEach((e=>{this.messagesById.delete(e)}));a.messages.length>0?this.messagesByFile.set(e,i):this.messagesByFile.delete(e);const n=this.haveMessagesChanged(o,i);return{...a,changed:n}}haveMessagesChanged(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&&this.areReferencesEqual(e.references,s.references)}areReferencesEqual(e,s){if(!e&&!s)return!0;if(!e||!s)return!1;if(e.length!==s.length)return!1;for(let t=0;t<e.length;t++)if(e[t].path!==s[t].path)return!1;return!0}async save(){return this.saveScheduler.schedule((()=>this.saveImpl()))}async saveImpl(){const e=Array.from(this.messagesById.values()),s=await this.getPersister();await s.write(this.config.sourceLocale,e);for(const e of await this.getTargetLocales())await this.saveLocale(e);return e.length}async saveLocale(e){const s=Array.from(this.messagesById.values()),t=await this.getPersister(),a=this.lastWriteByLocale.get(e),o=await t.getLastModified(e);if(o&&a&&o>a){const s=await t.read(e),a=this.translationsByTargetLocale.get(e);for(const e of s)a.set(e.id,e.message)}const r=this.translationsByTargetLocale.get(e),i=s.map((e=>({...e,message:r.get(e.id)||""})));await t.write(e,i);const c=await t.getLastModified(e);this.lastWriteByLocale.set(e,c)}onLocalesChange=async e=>{for(const s of e.added){const e=new Map;this.translationsByTargetLocale.set(s,e);const t=await this.loadLocaleMessages(s);for(const s of t)e.set(s.id,s.message);await this.saveLocale(s)}for(const s of e.removed)this.translationsByTargetLocale.delete(s),this.lastWriteByLocale.delete(s)};destroy(){this.saveScheduler.destroy(),this.catalogLocales&&this.isDevelopment&&this.catalogLocales.unsubscribeLocalesChange(this.onLocalesChange)}}export{n as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"path";class
|
|
1
|
+
import t from"path";class i{static EXTENSIONS=["ts","tsx","js","jsx"];static IGNORED_DIRECTORIES=["node_modules",".next",".git"];static isSourceFile(s){const e=t.extname(s);return i.EXTENSIONS.map((t=>"."+t)).includes(e)}static shouldEnterDirectory(s,e){const r=t.basename(s);return!i.IGNORED_DIRECTORIES.includes(r)||i.isIgnoredDirectoryExplicitlyIncluded(s,e)}static isIgnoredDirectoryExplicitlyIncluded(t,s){return s.some((s=>i.isWithinPath(s,t)))}static isWithinPath(i,s){const e=t.relative(s,i);return""===e||!e.startsWith("..")}}export{i as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"fs/promises";import
|
|
1
|
+
import e from"fs/promises";import i from"path";import r from"./SourceFileFilter.js";class t{static async walkSourceFiles(o,s,a=[]){const l=await e.readdir(o,{withFileTypes:!0});for(const e of l){const l=i.join(o,e.name);if(e.isDirectory()){if(!r.shouldEnterDirectory(l,s))continue;await t.walkSourceFiles(l,s,a)}else r.isSourceFile(e.name)&&a.push(l)}return a}static async getSourceFiles(e){return(await Promise.all(e.map((i=>t.walkSourceFiles(i,e))))).flat()}}export{t as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{normalizeTrailingSlash as e,getSortedPathnames as t,matchesPathname as n,prefixPathname as r,getLocalePrefix as o,templateToRegex as c,getLocalizedTemplate as i}from"../shared/utils.js";function s(e,r,o){const c=t(Object.keys(e));for(const t of c){const c=e[t];if("string"==typeof c){if(n(c,r))return[void 0,t]}else{const s=Object.entries(c),f=s.findIndex((([e])=>e===o));f>0&&s.unshift(s.splice(f,1)[0]);for(const[o]of s){const c=i(e[t],o,t);if(n(c,r))return[o,t]}}}for(const t of Object.keys(e))if(n(t,r))return[void 0,t];return[void 0,void 0]}function f(t,n,r,o){let c="";return c+=h(r,d(n,t)),c=e(c),c}function l(t,n,r){t.endsWith("/")||(t+="/");const o=u(n,r),c=new RegExp(`^(${o.map((([,e])=>e.replaceAll("/","\\/"))).join("|")})/(.*)`,"i"),i=t.match(c);let s=i?"/"+i[2]:t;return"/"!==s&&(s=e(s)),s}function u(e,t,n=!0){const r=e.map((e=>[e,o(e,t)]));return n&&r.sort(((e,t)=>t[1].length-e[1].length)),r}function a(e,t,n,r){const o=u(t,n);r&&o.sort((([e],[t])=>{if(e===r.defaultLocale)return-1;if(t===r.defaultLocale)return 1;const n=r.locales.includes(e),o=r.locales.includes(t);return n&&!o?-1:!n&&o?1:0}));for(const[t,n]of o){let r,o;if(e===n||e.startsWith(n+"/"))r=o=!0;else{const t=e.toLowerCase(),c=n.toLowerCase();(t===c||t.startsWith(c+"/"))&&(r=!1,o=!0)}if(o)return{locale:t,prefix:n,matchedPrefix:e.slice(0,n.length),exact:r}}}function d(t,n){const r=e(n),o=e(t),i=c(o).exec(r);if(!i)return;const s={};for(let e=1;e<i.length;e++){const t=
|
|
1
|
+
import{normalizeTrailingSlash as e,getSortedPathnames as t,matchesPathname as n,prefixPathname as r,getLocalePrefix as o,templateToRegex as c,getLocalizedTemplate as i}from"../shared/utils.js";function s(e,r,o){const c=t(Object.keys(e));for(const t of c){const c=e[t];if("string"==typeof c){if(n(c,r))return[void 0,t]}else{const s=Object.entries(c),f=s.findIndex((([e])=>e===o));f>0&&s.unshift(s.splice(f,1)[0]);for(const[o]of s){const c=i(e[t],o,t);if(n(c,r))return[o,t]}}}for(const t of Object.keys(e))if(n(t,r))return[void 0,t];return[void 0,void 0]}function f(t,n,r,o){let c="";return c+=h(r,d(n,t)),c=e(c),c}function l(t,n,r){t.endsWith("/")||(t+="/");const o=u(n,r),c=new RegExp(`^(${o.map((([,e])=>e.replaceAll("/","\\/"))).join("|")})/(.*)`,"i"),i=t.match(c);let s=i?"/"+i[2]:t;return"/"!==s&&(s=e(s)),s}function u(e,t,n=!0){const r=e.map((e=>[e,o(e,t)]));return n&&r.sort(((e,t)=>t[1].length-e[1].length)),r}function a(e,t,n,r){const o=u(t,n);r&&o.sort((([e],[t])=>{if(e===r.defaultLocale)return-1;if(t===r.defaultLocale)return 1;const n=r.locales.includes(e),o=r.locales.includes(t);return n&&!o?-1:!n&&o?1:0}));for(const[t,n]of o){let r,o;if(e===n||e.startsWith(n+"/"))r=o=!0;else{const t=e.toLowerCase(),c=n.toLowerCase();(t===c||t.startsWith(c+"/"))&&(r=!1,o=!0)}if(o)return{locale:t,prefix:n,matchedPrefix:e.slice(0,n.length),exact:r}}}function d(t,n){const r=e(n),o=e(t),i=c(o).exec(r);if(!i)return;const s={},f=o.match(/\[([^\]]+)\]/g)??[];for(let e=1;e<i.length;e++){const t=f[e-1];if(!t)continue;const n=t.replace(/[[\]]/g,""),r=i[e]??"";s[n]=r}return s}function h(e,t){if(!t)return e;let n=e=e.replace(/\[\[/g,"[").replace(/\]\]/g,"]");return Object.entries(t).forEach((([e,t])=>{n=n.replace(`[${e}]`,t)})),n}function p(e,t,n){let o=e;return t&&(o=r(t,o)),n&&(o+=n),o}function g(e){return e.get("x-forwarded-host")??e.get("host")??void 0}function x(e,t){return t.defaultLocale===e||t.locales.includes(e)}function m(e,t,n){let r;return e&&x(t,e)&&(r=e),r||(r=n.find((e=>e.defaultLocale===t))),r||(r=n.find((e=>e.locales.includes(t)))),r}function j(t,n){return e(n+t)}function L(e){return`/${e}`}function v(e){return e.replace(/\\/g,"%5C").replace(/\/+/g,"/")}export{j as applyBasePath,p as formatPathname,h as formatPathnameTemplate,f as formatTemplatePathname,m as getBestMatchingDomain,g as getHost,s as getInternalTemplate,L as getLocaleAsPrefix,u as getLocalePrefixes,l as getNormalizedPathname,a as getPathnameMatch,d as getRouteParams,x as isLocaleSupportedOnDomain,v as sanitizePathname};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"fs";import t from"path";import r from"../extractor/source/SourceFileFilter.js";import{isNextJs16OrHigher as s,hasStableTurboConfig as n}from"./nextFlags.js";import{throwError as o}from"./utils.js";function a(e){return[`${e}.ts`,`${e}.tsx`,`${e}.js`,`${e}.jsx`]}function i(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)||o(`Could not find i18n config at ${r}, please provide a valid path.`),r;for(const e of[...a("./i18n/request"),...a("./src/i18n/request")])if(n(e))return e;o("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 l(e,a){const l={};function u(){const t=e.experimental;return t.srcPath&&t.messages||o("`srcPath` and `messages` are required when using `extractor`."),{loader:"next-intl/extractor/extractionLoader",options:{srcPath:t.srcPath,sourceLocale:t.extract.sourceLocale,messages:t.messages}}}function c(){return{loader:"next-intl/extractor/catalogLoader",options:{messages:e.experimental.messages}}}function p(){return a?.turbopack?.rules||a?.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)&&o("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 m={"next-intl/config":i(e.requestConfig)};let f;e.experimental?.extract
|
|
1
|
+
import e from"fs";import t from"path";import r from"../extractor/source/SourceFileFilter.js";import{isNextJs16OrHigher as s,hasStableTurboConfig as n}from"./nextFlags.js";import{throwError as o}from"./utils.js";function a(e){return[`${e}.ts`,`${e}.tsx`,`${e}.js`,`${e}.jsx`]}function i(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)||o(`Could not find i18n config at ${r}, please provide a valid path.`),r;for(const e of[...a("./i18n/request"),...a("./src/i18n/request")])if(n(e))return e;o("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 l(e,a){const l={};function u(){const t=e.experimental;return t.srcPath&&t.messages||o("`srcPath` and `messages` are required when using `extractor`."),{loader:"next-intl/extractor/extractionLoader",options:{srcPath:t.srcPath,sourceLocale:t.extract.sourceLocale,messages:t.messages}}}function c(){return{loader:"next-intl/extractor/catalogLoader",options:{messages:e.experimental.messages}}}function p(){return a?.turbopack?.rules||a?.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)&&o("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 m={"next-intl/config":i(e.requestConfig)};let f;if(e.experimental?.extract){s()||o("Message extraction requires Next.js 16 or higher."),f??=p();const t=(Array.isArray(e.experimental.srcPath)?e.experimental.srcPath:[e.experimental.srcPath]).map((e=>e.endsWith("/")?e.slice(0,-1):e));x(f,`*.{${r.EXTENSIONS.join(",")}}`,{loaders:[u()],condition:{path:`{${t.join(",")}}/**/*`,content:/(useExtracted|getExtracted)/}})}e.experimental?.messages&&(s()||o("Message catalog loading requires Next.js 16 or higher."),f??=p(),x(f,`*.${e.experimental.messages.format}`,{loaders:[c()],condition:{path:`${e.experimental.messages.path}/**/*`},as:"*.js"})),n()&&!a?.experimental?.turbo?l.turbopack={...a?.turbopack,...f&&{rules:f},resolveAlias:{...a?.turbopack?.resolveAlias,...m}}:l.experimental={...a?.experimental,turbo:{...a?.experimental?.turbo,...f&&{rules:f},resolveAlias:{...a?.experimental?.turbo?.resolveAlias,...m}}}}else l.webpack=function(s,n){if(s.resolve||(s.resolve={}),s.resolve.alias||(s.resolve.alias={}),s.resolve.alias["next-intl/config"]=t.resolve(s.context,i(e.requestConfig,s.context)),e.experimental?.extract){s.module||(s.module={}),s.module.rules||(s.module.rules=[]);const n=e.experimental.srcPath;s.module.rules.push({test:new RegExp(`\\.(${r.EXTENSIONS.join("|")})$`),include:Array.isArray(n)?n.map((e=>t.resolve(s.context,e))):t.resolve(s.context,n||""),use:[u()]})}return e.experimental?.messages&&(s.module||(s.module={}),s.module.rules||(s.module.rules=[]),s.module.rules.push({test:new RegExp(`\\.${e.experimental.messages.format}$`),include:t.resolve(s.context,e.experimental.messages.path),use:[c()],type:"javascript/auto"})),"function"==typeof a?.webpack?a.webpack(s,n):s};return a?.trailingSlash&&(l.env={...a.env,_next_intl_trailing_slash:"true"}),Object.assign({},a,l)}export{l as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function n(n){return function(n){return"object"==typeof n?null==n.host&&null==n.hostname:!/^[a-z]+:/i.test(n)}(n)&&!function(n){const t="object"==typeof n?n.pathname:n;return null!=t&&!t.startsWith("/")}(n)}function t(n,t){return n.replace(new RegExp(`^${t}`),"")||"/"}function e(n,t){let e=n;return/^\/(\?.*)?$/.test(t)&&(t=t.slice(1)),e+=t,e}function r(n,t){return t===n||t.startsWith(`${n}/`)}function u(n,t,e){return"string"==typeof n?n:n[t]||e}function i(n){const t=function(){try{return"true"===process.env._next_intl_trailing_slash}catch{return!1}}(),[e,...r]=n.split("#"),u=r.join("#");let i=e;if("/"!==i){const n=i.endsWith("/");t&&!n?i+="/":!t&&n&&(i=i.slice(0,-1))}return u&&(i+="#"+u),i}function c(n,t){const e=i(n),r=i(t);return s(e).test(r)}function o(n,t){return"never"!==t.mode&&t.prefixes?.[n]||f(n)}function f(n){return"/"+n}function s(n){const t=n.replace(
|
|
1
|
+
function n(n){return function(n){return"object"==typeof n?null==n.host&&null==n.hostname:!/^[a-z]+:/i.test(n)}(n)&&!function(n){const t="object"==typeof n?n.pathname:n;return null!=t&&!t.startsWith("/")}(n)}function t(n,t){return n.replace(new RegExp(`^${t}`),"")||"/"}function e(n,t){let e=n;return/^\/(\?.*)?$/.test(t)&&(t=t.slice(1)),e+=t,e}function r(n,t){return t===n||t.startsWith(`${n}/`)}function u(n,t,e){return"string"==typeof n?n:n[t]||e}function i(n){const t=function(){try{return"true"===process.env._next_intl_trailing_slash}catch{return!1}}(),[e,...r]=n.split("#"),u=r.join("#");let i=e;if("/"!==i){const n=i.endsWith("/");t&&!n?i+="/":!t&&n&&(i=i.slice(0,-1))}return u&&(i+="#"+u),i}function c(n,t){const e=i(n),r=i(t);return s(e).test(r)}function o(n,t){return"never"!==t.mode&&t.prefixes?.[n]||f(n)}function f(n){return"/"+n}function s(n){const t=n.replace(/\/\[\[(\.\.\.[^\]]+)\]\]/g,"(?:/(.*))?").replace(/\[\[(\.\.\.[^\]]+)\]\]/g,"(?:/(.*))?").replace(/\[(\.\.\.[^\]]+)\]/g,"(.+)").replace(/\[([^\]]+)\]/g,"([^/]+)");return new RegExp(`^${t}$`)}function l(n){return n.includes("[[...")}function p(n){return n.includes("[...")}function a(n){return n.includes("[")}function h(n,t){const e=n.split("/"),r=t.split("/"),u=Math.max(e.length,r.length);for(let n=0;n<u;n++){const t=e[n],u=r[n];if(!t&&u)return-1;if(t&&!u)return 1;if(t||u){if(!a(t)&&a(u))return-1;if(a(t)&&!a(u))return 1;if(!p(t)&&p(u))return-1;if(p(t)&&!p(u))return 1;if(!l(t)&&l(u))return-1;if(l(t)&&!l(u))return 1}}return 0}function g(n){return n.sort(h)}function x(n){return"function"==typeof n.then}export{f as getLocaleAsPrefix,o as getLocalePrefix,u as getLocalizedTemplate,g as getSortedPathnames,r as hasPathnamePrefixed,n as isLocalizableHref,x as isPromise,c as matchesPathname,i as normalizeTrailingSlash,e as prefixPathname,s as templateToRegex,t as unprefixPathname};
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export default class SourceFileFilter {
|
|
2
2
|
static readonly EXTENSIONS: string[];
|
|
3
|
+
private static readonly IGNORED_DIRECTORIES;
|
|
3
4
|
static isSourceFile(filePath: string): boolean;
|
|
5
|
+
static shouldEnterDirectory(dirPath: string, srcPaths: Array<string>): boolean;
|
|
6
|
+
private static isIgnoredDirectoryExplicitlyIncluded;
|
|
7
|
+
private static isWithinPath;
|
|
4
8
|
}
|
|
@@ -11,7 +11,7 @@ export type ExtractedMessage = {
|
|
|
11
11
|
export type MessagesConfig = {
|
|
12
12
|
path: string;
|
|
13
13
|
format: MessagesFormat;
|
|
14
|
-
locales: 'infer' |
|
|
14
|
+
locales: 'infer' | ReadonlyArray<Locale>;
|
|
15
15
|
};
|
|
16
16
|
export type ExtractorConfig = {
|
|
17
17
|
srcPath: string | Array<string>;
|
|
@@ -14,7 +14,7 @@ export type PluginConfig = {
|
|
|
14
14
|
/** Defines the format for how your messages are stored. */
|
|
15
15
|
format: MessagesFormat;
|
|
16
16
|
/** Either automatically infer the locales based on catalog files in `path` or explicitly define them. */
|
|
17
|
-
locales: 'infer' |
|
|
17
|
+
locales: 'infer' | ReadonlyArray<string>;
|
|
18
18
|
};
|
|
19
19
|
/** Enables the usage of `useExtracted`, to be used in combination with `srcPath` and `messages`. */
|
|
20
20
|
extract?: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-intl",
|
|
3
|
-
"version": "4.5.
|
|
3
|
+
"version": "4.5.2",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"author": "Jan Amann <jan@amann.work>",
|
|
6
6
|
"funding": [
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
"@formatjs/intl-localematcher": "^0.5.4",
|
|
128
128
|
"@swc/core": "^1.13.19",
|
|
129
129
|
"negotiator": "^1.0.0",
|
|
130
|
-
"use-intl": "^4.5.
|
|
130
|
+
"use-intl": "^4.5.2"
|
|
131
131
|
},
|
|
132
132
|
"peerDependencies": {
|
|
133
133
|
"next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
|
|
@@ -139,5 +139,5 @@
|
|
|
139
139
|
"optional": true
|
|
140
140
|
}
|
|
141
141
|
},
|
|
142
|
-
"gitHead": "
|
|
142
|
+
"gitHead": "56b7de6ac710a633e7880a295b6750b502f24edd"
|
|
143
143
|
}
|