next-intl 4.14.0 → 4.14.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.
@@ -1326,6 +1326,23 @@ function normalizeTurbopackAliasPath(pathname) {
1326
1326
  // break resolution in dev (see `next-intl/config` alias path style).
1327
1327
  return pathname.replace(/\\/g, '/');
1328
1328
  }
1329
+
1330
+ /**
1331
+ * Turbopack validates loader options by comparing them to their JSON round-trip
1332
+ * (`isDeepStrictEqual(options, JSON.parse(JSON.stringify(options)))`). Since
1333
+ * `JSON.stringify` drops keys with an `undefined` value, such a key would always
1334
+ * fail that check, therefore they're removed here.
1335
+ * https://github.com/amannn/next-intl/issues/2394
1336
+ */
1337
+ function pruneUndefined(value) {
1338
+ if (Array.isArray(value)) {
1339
+ return value.map(pruneUndefined);
1340
+ }
1341
+ if (value !== null && typeof value === 'object') {
1342
+ return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined).map(([key, entry]) => [key, pruneUndefined(entry)]));
1343
+ }
1344
+ return value;
1345
+ }
1329
1346
  function resolveI18nPath(providedPath, cwd) {
1330
1347
  function resolvePath(pathname) {
1331
1348
  const parts = [];
@@ -1377,7 +1394,7 @@ function getNextConfig(pluginConfig, nextConfig, extractorConfig) {
1377
1394
  function getExtractMessagesLoaderConfig(config) {
1378
1395
  return {
1379
1396
  loader: 'next-intl/extractor/extractionLoader',
1380
- options: config
1397
+ options: pruneUndefined(config)
1381
1398
  };
1382
1399
  }
1383
1400
  function getCatalogLoaderConfig() {
@@ -1387,15 +1404,13 @@ function getNextConfig(pluginConfig, nextConfig, extractorConfig) {
1387
1404
  const sourceLocale = messages.sourceLocale ?? (typeof experimental.extract === 'object' ? experimental.extract.sourceLocale : undefined);
1388
1405
  return {
1389
1406
  loader: 'next-intl/extractor/catalogLoader',
1390
- options: {
1407
+ options: pruneUndefined({
1391
1408
  messages: {
1392
1409
  format: messages.format,
1393
- ...(messages.precompile !== undefined && {
1394
- precompile: messages.precompile
1395
- }),
1410
+ precompile: messages.precompile,
1396
1411
  sourceLocale
1397
1412
  }
1398
- }
1413
+ })
1399
1414
  };
1400
1415
  }
1401
1416
  function getTurboRules() {
@@ -17,6 +17,23 @@ function normalizeTurbopackAliasPath(pathname) {
17
17
  // break resolution in dev (see `next-intl/config` alias path style).
18
18
  return pathname.replace(/\\/g, '/');
19
19
  }
20
+
21
+ /**
22
+ * Turbopack validates loader options by comparing them to their JSON round-trip
23
+ * (`isDeepStrictEqual(options, JSON.parse(JSON.stringify(options)))`). Since
24
+ * `JSON.stringify` drops keys with an `undefined` value, such a key would always
25
+ * fail that check, therefore they're removed here.
26
+ * https://github.com/amannn/next-intl/issues/2394
27
+ */
28
+ function pruneUndefined(value) {
29
+ if (Array.isArray(value)) {
30
+ return value.map(pruneUndefined);
31
+ }
32
+ if (value !== null && typeof value === 'object') {
33
+ return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined).map(([key, entry]) => [key, pruneUndefined(entry)]));
34
+ }
35
+ return value;
36
+ }
20
37
  function resolveI18nPath(providedPath, cwd) {
21
38
  function resolvePath(pathname) {
22
39
  const parts = [];
@@ -68,7 +85,7 @@ function getNextConfig(pluginConfig, nextConfig, extractorConfig) {
68
85
  function getExtractMessagesLoaderConfig(config) {
69
86
  return {
70
87
  loader: 'next-intl/extractor/extractionLoader',
71
- options: config
88
+ options: pruneUndefined(config)
72
89
  };
73
90
  }
74
91
  function getCatalogLoaderConfig() {
@@ -78,15 +95,13 @@ function getNextConfig(pluginConfig, nextConfig, extractorConfig) {
78
95
  const sourceLocale = messages.sourceLocale ?? (typeof experimental.extract === 'object' ? experimental.extract.sourceLocale : undefined);
79
96
  return {
80
97
  loader: 'next-intl/extractor/catalogLoader',
81
- options: {
98
+ options: pruneUndefined({
82
99
  messages: {
83
100
  format: messages.format,
84
- ...(messages.precompile !== undefined && {
85
- precompile: messages.precompile
86
- }),
101
+ precompile: messages.precompile,
87
102
  sourceLocale
88
103
  }
89
- }
104
+ })
90
105
  };
91
106
  }
92
107
  function getTurboRules() {
@@ -1 +1 @@
1
- import e from"fs";import{createRequire as t}from"module";import r from"path";import{getFormatExtension as o}from"../extractor/format/index.js";import{normalizeMessagesCatalogPaths as s}from"../extractor/normalizeExtractorConfig.js";import n from"../extractor/source/SourceFileFilter.js";import{isDevelopmentOrNextBuild as i}from"./config.js";import{isNextJs16OrHigher as a,hasStableTurboConfig as l}from"./nextFlags.js";import{throwError as u}from"./utils.js";const c=t(import.meta.url);function m(e){return[`${e}.ts`,`${e}.tsx`,`${e}.js`,`${e}.jsx`]}function p(t,o){function s(t){return e.existsSync(function(e){const t=[];return o&&t.push(o),t.push(e),r.resolve(...t)}(t))}if(t)return i&&!s(t)&&u(`Could not find i18n config at ${t}, please provide a valid path.`),t;for(const e of[...m("./i18n/request"),...m("./src/i18n/request")])if(s(e))return e;return i&&u("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 './path/to/i18n/request.tsx'\n);"),s("./src")?"./src/i18n/request.ts":"./i18n/request.ts"}function f(e,t,i){const m=null!=process.env.TURBOPACK,f=m||a(),x={};let g=[];function d(e){return{loader:"next-intl/extractor/extractionLoader",options:e}}function v(){const t=e.experimental,r=t.messages,o=r.sourceLocale??("object"==typeof t.extract?t.extract.sourceLocale:void 0);return{loader:"next-intl/extractor/catalogLoader",options:{messages:{format:r.format,...void 0!==r.precompile&&{precompile:r.precompile},sourceLocale:o}}}}function h(){return t?.turbopack?.rules||t?.experimental?.turbo?.rules||{}}function j(e,t,r){e[t]?Array.isArray(e[t])?e[t].push(r):e[t]=[e[t],r]:e[t]=r}if(e.experimental?.messages&&(g=s(e.experimental.messages.path)),f){e.requestConfig&&r.isAbsolute(e.requestConfig)&&u("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 s={"next-intl/config":p(e.requestConfig)};if(e.experimental?.messages?.precompile){let e=r.relative(process.cwd(),c.resolve("use-intl/format-message/format-only"));e.startsWith(".")||(e=`./${e}`),s["use-intl/format-message"]=e.replace(/\\/g,"/")}let m;if(e.experimental?.extract&&(a()||u("Message extraction requires Next.js 16 or higher."),m??=h(),j(m,`*.{${n.EXTENSIONS.join(",")}}`,{loaders:[d(i)],condition:{content:/(useExtracted|getExtracted)/}})),e.experimental?.messages){a()||u("Message catalog loading requires Next.js 16 or higher."),m??=h();j(m,`*${o(e.experimental.messages.format)}`,{loaders:[v()],condition:{path:`{${g.join(",")}}/**/*`},as:"*.js"})}l()&&!t?.experimental?.turbo?x.turbopack={...t?.turbopack,...m&&{rules:m},resolveAlias:{...t?.turbopack?.resolveAlias,...s}}:x.experimental={...t?.experimental,turbo:{...t?.experimental?.turbo,...m&&{rules:m},resolveAlias:{...t?.experimental?.turbo?.resolveAlias,...s}}}}return m||(x.webpack=function(s,a){if(s.resolve||(s.resolve={}),s.resolve.alias||(s.resolve.alias={}),s.resolve.alias["next-intl/config"]=r.resolve(s.context,p(e.requestConfig,s.context)),e.experimental?.messages?.precompile&&(s.resolve.alias["use-intl/format-message"]=c.resolve("use-intl/format-message/format-only")),e.experimental?.extract&&(s.module||(s.module={}),s.module.rules||(s.module.rules=[]),s.module.rules.push({test:new RegExp(`\\.(${n.EXTENSIONS.join("|")})$`),use:[d(i)]})),e.experimental?.messages){s.module||(s.module={}),s.module.rules||(s.module.rules=[]);const t=o(e.experimental.messages.format);s.module.rules.push({test:new RegExp(`${t.replace(/\./g,"\\.")}$`),include:g.map((e=>r.resolve(s.context,e))),use:[v()],type:"javascript/auto"})}return"function"==typeof t?.webpack?t.webpack(s,a):s}),t?.trailingSlash&&(x.env={...t.env,_next_intl_trailing_slash:"true"}),Object.assign({},t,x)}export{f as default};
1
+ import e from"fs";import{createRequire as t}from"module";import r from"path";import{getFormatExtension as o}from"../extractor/format/index.js";import{normalizeMessagesCatalogPaths as s}from"../extractor/normalizeExtractorConfig.js";import n from"../extractor/source/SourceFileFilter.js";import{isDevelopmentOrNextBuild as i}from"./config.js";import{isNextJs16OrHigher as a,hasStableTurboConfig as l}from"./nextFlags.js";import{throwError as u}from"./utils.js";const c=t(import.meta.url);function m(e){return[`${e}.ts`,`${e}.tsx`,`${e}.js`,`${e}.jsx`]}function p(e){return Array.isArray(e)?e.map(p):null!==e&&"object"==typeof e?Object.fromEntries(Object.entries(e).filter((([,e])=>void 0!==e)).map((([e,t])=>[e,p(t)]))):e}function f(t,o){function s(t){return e.existsSync(function(e){const t=[];return o&&t.push(o),t.push(e),r.resolve(...t)}(t))}if(t)return i&&!s(t)&&u(`Could not find i18n config at ${t}, please provide a valid path.`),t;for(const e of[...m("./i18n/request"),...m("./src/i18n/request")])if(s(e))return e;return i&&u("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 './path/to/i18n/request.tsx'\n);"),s("./src")?"./src/i18n/request.ts":"./i18n/request.ts"}function x(e,t,i){const m=null!=process.env.TURBOPACK,x=m||a(),g={};let d=[];function v(e){return{loader:"next-intl/extractor/extractionLoader",options:p(e)}}function j(){const t=e.experimental,r=t.messages,o=r.sourceLocale??("object"==typeof t.extract?t.extract.sourceLocale:void 0);return{loader:"next-intl/extractor/catalogLoader",options:p({messages:{format:r.format,precompile:r.precompile,sourceLocale:o}})}}function b(){return t?.turbopack?.rules||t?.experimental?.turbo?.rules||{}}function h(e,t,r){e[t]?Array.isArray(e[t])?e[t].push(r):e[t]=[e[t],r]:e[t]=r}if(e.experimental?.messages&&(d=s(e.experimental.messages.path)),x){e.requestConfig&&r.isAbsolute(e.requestConfig)&&u("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 s={"next-intl/config":f(e.requestConfig)};if(e.experimental?.messages?.precompile){let e=r.relative(process.cwd(),c.resolve("use-intl/format-message/format-only"));e.startsWith(".")||(e=`./${e}`),s["use-intl/format-message"]=e.replace(/\\/g,"/")}let m;if(e.experimental?.extract&&(a()||u("Message extraction requires Next.js 16 or higher."),m??=b(),h(m,`*.{${n.EXTENSIONS.join(",")}}`,{loaders:[v(i)],condition:{content:/(useExtracted|getExtracted)/}})),e.experimental?.messages){a()||u("Message catalog loading requires Next.js 16 or higher."),m??=b();h(m,`*${o(e.experimental.messages.format)}`,{loaders:[j()],condition:{path:`{${d.join(",")}}/**/*`},as:"*.js"})}l()&&!t?.experimental?.turbo?g.turbopack={...t?.turbopack,...m&&{rules:m},resolveAlias:{...t?.turbopack?.resolveAlias,...s}}:g.experimental={...t?.experimental,turbo:{...t?.experimental?.turbo,...m&&{rules:m},resolveAlias:{...t?.experimental?.turbo?.resolveAlias,...s}}}}return m||(g.webpack=function(s,a){if(s.resolve||(s.resolve={}),s.resolve.alias||(s.resolve.alias={}),s.resolve.alias["next-intl/config"]=r.resolve(s.context,f(e.requestConfig,s.context)),e.experimental?.messages?.precompile&&(s.resolve.alias["use-intl/format-message"]=c.resolve("use-intl/format-message/format-only")),e.experimental?.extract&&(s.module||(s.module={}),s.module.rules||(s.module.rules=[]),s.module.rules.push({test:new RegExp(`\\.(${n.EXTENSIONS.join("|")})$`),use:[v(i)]})),e.experimental?.messages){s.module||(s.module={}),s.module.rules||(s.module.rules=[]);const t=o(e.experimental.messages.format);s.module.rules.push({test:new RegExp(`${t.replace(/\./g,"\\.")}$`),include:d.map((e=>r.resolve(s.context,e))),use:[j()],type:"javascript/auto"})}return"function"==typeof t?.webpack?t.webpack(s,a):s}),t?.trailingSlash&&(g.env={...t.env,_next_intl_trailing_slash:"true"}),Object.assign({},t,g)}export{x as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-intl",
3
- "version": "4.14.0",
3
+ "version": "4.14.2",
4
4
  "sideEffects": false,
5
5
  "author": "Jan Amann <jan@amann.work>",
6
6
  "funding": [
@@ -124,20 +124,20 @@
124
124
  "next.js"
125
125
  ],
126
126
  "dependencies": {
127
- "@eloqnt/config": "^0.0.2",
128
- "@eloqnt/format-json": "^0.0.3",
129
- "@eloqnt/format-po": "^0.0.3",
127
+ "@eloqnt/config": "^0.1.0",
128
+ "@eloqnt/format-json": "^0.1.0",
129
+ "@eloqnt/format-po": "^0.1.0",
130
130
  "@formatjs/intl-localematcher": "^0.8.1",
131
131
  "@parcel/watcher": "^2.4.1",
132
132
  "@swc/core": "~1.16.0",
133
- "icu-minify": "^4.14.0",
133
+ "icu-minify": "^4.14.2",
134
134
  "negotiator": "^1.0.0",
135
- "next-intl-swc-plugin-extractor": "4.14.0",
136
- "use-intl": "^4.14.0"
135
+ "next-intl-swc-plugin-extractor": "4.14.2",
136
+ "use-intl": "^4.14.2"
137
137
  },
138
138
  "peerDependencies": {
139
139
  "next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
140
140
  "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0"
141
141
  },
142
- "gitHead": "38845ed081a82fd2ab1bae8788620ca3d36334f5"
142
+ "gitHead": "3259beb76120614af8b48e814c56324ad71ccb61"
143
143
  }