next-intl 4.14.3 → 4.14.5
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 +10 -2
- package/dist/esm/development/navigation/react-client/createNavigation.js +5 -6
- package/dist/esm/development/navigation/shared/BaseLink.js +2 -8
- package/dist/esm/development/navigation/shared/syncLocaleCookie.js +3 -9
- package/dist/esm/development/navigation/shared/utils.js +6 -5
- package/dist/esm/development/plugin/getNextConfig.js +10 -2
- package/dist/esm/production/navigation/react-client/createNavigation.js +1 -1
- package/dist/esm/production/navigation/shared/BaseLink.js +1 -1
- package/dist/esm/production/navigation/shared/syncLocaleCookie.js +1 -1
- package/dist/esm/production/navigation/shared/utils.js +1 -1
- package/dist/esm/production/plugin/getNextConfig.js +1 -1
- package/dist/types/navigation/shared/syncLocaleCookie.d.ts +1 -1
- package/dist/types/navigation/shared/utils.d.ts +1 -1
- package/package.json +5 -5
|
@@ -1570,10 +1570,18 @@ function getNextConfig(pluginConfig, nextConfig, extractorConfig) {
|
|
|
1570
1570
|
}
|
|
1571
1571
|
|
|
1572
1572
|
// Forward config
|
|
1573
|
+
const env = {};
|
|
1573
1574
|
if (nextConfig?.trailingSlash) {
|
|
1575
|
+
env._next_intl_trailing_slash = 'true';
|
|
1576
|
+
}
|
|
1577
|
+
if (nextConfig?.basePath) {
|
|
1578
|
+
env._next_intl_base_path = nextConfig.basePath;
|
|
1579
|
+
}
|
|
1580
|
+
// Note that `undefined` values are not supported by Turbopack
|
|
1581
|
+
if (Object.keys(env).length > 0) {
|
|
1574
1582
|
nextIntlConfig.env = {
|
|
1575
|
-
...nextConfig
|
|
1576
|
-
|
|
1583
|
+
...nextConfig?.env,
|
|
1584
|
+
...env
|
|
1577
1585
|
};
|
|
1578
1586
|
}
|
|
1579
1587
|
return Object.assign({}, nextConfig, nextIntlConfig);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useRouter
|
|
1
|
+
import { useRouter } from 'next/navigation';
|
|
2
2
|
import { useMemo } from 'react';
|
|
3
3
|
import { useLocale } from 'use-intl';
|
|
4
4
|
import createSharedNavigationFns from '../shared/createSharedNavigationFns.js';
|
|
@@ -15,7 +15,7 @@ function createNavigation(routing) {
|
|
|
15
15
|
} = createSharedNavigationFns(useLocale, routing);
|
|
16
16
|
|
|
17
17
|
/** @see https://next-intl.dev/docs/routing/navigation#usepathname */
|
|
18
|
-
function usePathname
|
|
18
|
+
function usePathname() {
|
|
19
19
|
const pathname = useBasePathname(config);
|
|
20
20
|
const locale = useLocale();
|
|
21
21
|
|
|
@@ -29,7 +29,6 @@ function createNavigation(routing) {
|
|
|
29
29
|
function useRouter$1() {
|
|
30
30
|
const router = useRouter();
|
|
31
31
|
const curLocale = useLocale();
|
|
32
|
-
const nextPathname = usePathname();
|
|
33
32
|
return useMemo(() => {
|
|
34
33
|
function createHandler(fn) {
|
|
35
34
|
return function handler(href, options) {
|
|
@@ -53,7 +52,7 @@ function createNavigation(routing) {
|
|
|
53
52
|
// @ts-expect-error -- This is fine
|
|
54
53
|
args.push(rest);
|
|
55
54
|
}
|
|
56
|
-
syncLocaleCookie(config.localeCookie,
|
|
55
|
+
syncLocaleCookie(config.localeCookie, curLocale, nextLocale);
|
|
57
56
|
fn(...args);
|
|
58
57
|
};
|
|
59
58
|
}
|
|
@@ -66,12 +65,12 @@ function createNavigation(routing) {
|
|
|
66
65
|
/** @see https://next-intl.dev/docs/routing/navigation#userouter */
|
|
67
66
|
prefetch: createHandler(router.prefetch)
|
|
68
67
|
};
|
|
69
|
-
}, [curLocale,
|
|
68
|
+
}, [curLocale, router]);
|
|
70
69
|
}
|
|
71
70
|
return {
|
|
72
71
|
...redirects,
|
|
73
72
|
Link,
|
|
74
|
-
usePathname
|
|
73
|
+
usePathname,
|
|
75
74
|
useRouter: useRouter$1,
|
|
76
75
|
getPathname
|
|
77
76
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import NextLink from 'next/link';
|
|
3
|
-
import { usePathname } from 'next/navigation';
|
|
4
3
|
import { forwardRef } from 'react';
|
|
5
4
|
import { useLocale } from 'use-intl';
|
|
6
5
|
import syncLocaleCookie from './syncLocaleCookie.js';
|
|
@@ -11,9 +10,7 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
11
10
|
const Link = NextLink;
|
|
12
11
|
|
|
13
12
|
// Links that change the locale are handled in a separate component,
|
|
14
|
-
// since
|
|
15
|
-
// requires a Suspense boundary when Cache Components are used. Due to
|
|
16
|
-
// this split, regular links are not subject to this requirement.
|
|
13
|
+
// since they require additional handling for syncing the locale cookie.
|
|
17
14
|
function LocaleChangingLink({
|
|
18
15
|
curLocale,
|
|
19
16
|
linkRef,
|
|
@@ -23,14 +20,11 @@ function LocaleChangingLink({
|
|
|
23
20
|
prefetch,
|
|
24
21
|
...rest
|
|
25
22
|
}) {
|
|
26
|
-
// The types aren't entirely correct here. Outside of Next.js
|
|
27
|
-
// `usePathname` can be called, but the return type is `null`.
|
|
28
|
-
const pathname = usePathname();
|
|
29
23
|
function onLinkClick(event) {
|
|
30
24
|
// Even though we force a prefix when changing locales,
|
|
31
25
|
// this could be a cache hit of the client-side router,
|
|
32
26
|
// therefore we sync the cookie to ensure it's up to date.
|
|
33
|
-
syncLocaleCookie(localeCookie,
|
|
27
|
+
syncLocaleCookie(localeCookie, curLocale, locale);
|
|
34
28
|
if (onClick) onClick(event);
|
|
35
29
|
}
|
|
36
30
|
if (prefetch && "development" !== 'production') {
|
|
@@ -5,23 +5,17 @@ import { getBasePath } from './utils.js';
|
|
|
5
5
|
* skip a request to the server due to its router cache.
|
|
6
6
|
* See https://github.com/amannn/next-intl/issues/786.
|
|
7
7
|
*/
|
|
8
|
-
function syncLocaleCookie(localeCookie,
|
|
8
|
+
function syncLocaleCookie(localeCookie, locale, nextLocale) {
|
|
9
9
|
const isSwitchingLocale = nextLocale !== locale && nextLocale != null;
|
|
10
|
-
if (!localeCookie || !isSwitchingLocale
|
|
11
|
-
// Theoretical case, we always have a pathname in a real app,
|
|
12
|
-
// only not when running e.g. in a simulated test environment
|
|
13
|
-
!pathname) {
|
|
10
|
+
if (!localeCookie || !isSwitchingLocale) {
|
|
14
11
|
return;
|
|
15
12
|
}
|
|
16
|
-
const basePath = getBasePath(pathname);
|
|
17
|
-
const hasBasePath = basePath !== '';
|
|
18
|
-
const defaultPath = hasBasePath ? basePath : '/';
|
|
19
13
|
const {
|
|
20
14
|
name,
|
|
21
15
|
...rest
|
|
22
16
|
} = localeCookie;
|
|
23
17
|
if (!rest.path) {
|
|
24
|
-
rest.path =
|
|
18
|
+
rest.path = getBasePath() || '/';
|
|
25
19
|
}
|
|
26
20
|
let localeCookieString = `${name}=${nextLocale};`;
|
|
27
21
|
for (const [key, value] of Object.entries(rest)) {
|
|
@@ -130,11 +130,12 @@ function getRoute(locale, pathname, pathnames) {
|
|
|
130
130
|
}
|
|
131
131
|
return pathname;
|
|
132
132
|
}
|
|
133
|
-
function getBasePath(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
function getBasePath() {
|
|
134
|
+
try {
|
|
135
|
+
// Provided via `env` setting in `next.config.js` via the plugin
|
|
136
|
+
return process.env._next_intl_base_path || '';
|
|
137
|
+
} catch {
|
|
138
|
+
return '';
|
|
138
139
|
}
|
|
139
140
|
}
|
|
140
141
|
function applyPathnamePrefix(pathname, locale, routing, force) {
|
|
@@ -261,10 +261,18 @@ function getNextConfig(pluginConfig, nextConfig, extractorConfig) {
|
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
// Forward config
|
|
264
|
+
const env = {};
|
|
264
265
|
if (nextConfig?.trailingSlash) {
|
|
266
|
+
env._next_intl_trailing_slash = 'true';
|
|
267
|
+
}
|
|
268
|
+
if (nextConfig?.basePath) {
|
|
269
|
+
env._next_intl_base_path = nextConfig.basePath;
|
|
270
|
+
}
|
|
271
|
+
// Note that `undefined` values are not supported by Turbopack
|
|
272
|
+
if (Object.keys(env).length > 0) {
|
|
265
273
|
nextIntlConfig.env = {
|
|
266
|
-
...nextConfig
|
|
267
|
-
|
|
274
|
+
...nextConfig?.env,
|
|
275
|
+
...env
|
|
268
276
|
};
|
|
269
277
|
}
|
|
270
278
|
return Object.assign({}, nextConfig, nextIntlConfig);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useRouter as e
|
|
1
|
+
import{useRouter as e}from"next/navigation";import{useMemo as t}from"react";import{useLocale as r}from"use-intl";import o from"../shared/createSharedNavigationFns.js";import n from"../shared/syncLocaleCookie.js";import{getRoute as a}from"../shared/utils.js";import s from"./useBasePathname.js";function i(i){const{Link:c,config:u,getPathname:m,...f}=o(r,i);return{...f,Link:c,usePathname:function(){const e=s(u),o=r();return t((()=>e&&u.pathnames?a(o,e,u.pathnames):e),[o,e])},useRouter:function(){const o=e(),a=r();return t((()=>{function e(e){return function(t,r){const{locale:o,...s}=r||{},i=[m({href:t,locale:o||a,forcePrefix:null!=o||void 0})];Object.keys(s).length>0&&i.push(s),n(u.localeCookie,a,o),e(...i)}}return{...o,push:e(o.push),replace:e(o.replace),prefetch:e(o.prefetch)}}),[a,o])},getPathname:m}}export{i as default};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import o from"next/link";import{
|
|
2
|
+
import o from"next/link";import{forwardRef as e}from"react";import{useLocale as r}from"use-intl";import l from"./syncLocaleCookie.js";import{jsx as c}from"react/jsx-runtime";const n=o;function t({curLocale:o,linkRef:e,locale:r,localeCookie:t,onClick:i,prefetch:f,...a}){return c(n,{ref:e,hrefLang:r,onClick:function(e){l(t,o,r),i&&i(e)},prefetch:!1,...a})}function i({locale:o,localeCookie:e,...l},i){const f=r();return null!=o&&o!==f?c(t,{curLocale:f,linkRef:i,locale:o,localeCookie:e,...l}):c(n,{ref:i,...l})}var f=e(i);export{f as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getBasePath as t}from"./utils.js";function e(e,o,n
|
|
1
|
+
import{getBasePath as t}from"./utils.js";function e(e,o,n){if(!e||!(n!==o&&null!=n))return;const{name:a,...f}=e;f.path||(f.path=t()||"/");let r=`${a}=${n};`;for(const[t,e]of Object.entries(f)){r+=`${"maxAge"===t?"max-age":t}`,"boolean"!=typeof e&&(r+="="+e),r+=";"}document.cookie=r}export{e as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getSortedPathnames as e,matchesPathname as
|
|
1
|
+
import{getSortedPathnames as e,matchesPathname as t,isLocalizableHref as n,prefixPathname as r,normalizeTrailingSlash as o,getLocalizedTemplate as a,getLocalePrefix as c}from"../../shared/utils.js";function i(e){return"string"==typeof e?{pathname:e}:e}function s(e){function t(e){return String(e)}const n=new URLSearchParams;for(const[r,o]of Object.entries(e))Array.isArray(o)?o.forEach((e=>{n.append(r,t(e))})):n.set(r,t(o));return"?"+n.toString()}function f({pathname:e,locale:t,params:n,pathnames:r,query:c}){function i(e){const i=r[e];let f;if(i){const r=a(i,t,e);f=r,n&&Object.entries(n).forEach((([e,t])=>{let n,r;Array.isArray(t)?(n=`(\\[)?\\[...${e}\\](\\])?`,r=t.map((e=>String(e))).join("/")):(n=`\\[${e}\\]`,r=String(t)),f=f.replace(new RegExp(n,"g"),(()=>r))})),f=f.replace(/\[\[\.\.\..+\]\]/g,""),f=function(e){return new URL(e,"http://l").pathname}(f)}else f=e;return f=o(f),c&&(f+=s(c)),f}if("string"==typeof e)return i(e);{const{pathname:t,...n}=e;return{...n,pathname:i(t)}}}function l(n,r,o){const c=e(Object.keys(o)),i=decodeURI(r);for(const e of c){const r=o[e];if("string"==typeof r){if(t(r,i))return e}else if(t(a(r,n,e),i))return e}return r}function u(){try{return process.env._next_intl_base_path||""}catch{return""}}function p(e,t,o,a){const{mode:i}=o.localePrefix;let s;if(void 0!==a)s=a;else if(n(e)){const e=o.domains?.find((e=>e.locales.includes(t))),n=e?.localePrefix||i;"always"===n?s=!0:"as-needed"===n&&(s=e?t!==e.defaultLocale:t!==o.defaultLocale)}return s?r(c(t,o.localePrefix),e):e}export{p as applyPathnamePrefix,f as compileLocalizedPathname,u as getBasePath,l as getRoute,i as normalizeNameOrNameWithParams,s as serializeSearchParams};
|
|
@@ -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
|
|
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 a}from"./config.js";import{isNextJs16OrHigher as i,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 a&&!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 a&&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,a){const m=null!=process.env.TURBOPACK,x=m||i(),g={};let d=[];function v(e){return{loader:"next-intl/extractor/extractionLoader",options:p(e)}}function b(){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 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&&(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&&(i()||u("Message extraction requires Next.js 16 or higher."),m??=h(),j(m,`*.{${n.EXTENSIONS.join(",")}}`,{loaders:[v(a)],condition:{content:/(useExtracted|getExtracted)/}})),e.experimental?.messages){i()||u("Message catalog loading requires Next.js 16 or higher."),m??=h();j(m,`*${o(e.experimental.messages.format)}`,{loaders:[b()],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}}}}m||(g.webpack=function(s,i){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(a)]})),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:[b()],type:"javascript/auto"})}return"function"==typeof t?.webpack?t.webpack(s,i):s});const y={};return t?.trailingSlash&&(y._next_intl_trailing_slash="true"),t?.basePath&&(y._next_intl_base_path=t.basePath),Object.keys(y).length>0&&(g.env={...t?.env,...y}),Object.assign({},t,g)}export{x as default};
|
|
@@ -5,4 +5,4 @@ import type { InitializedLocaleCookieConfig } from '../../routing/config.js';
|
|
|
5
5
|
* skip a request to the server due to its router cache.
|
|
6
6
|
* See https://github.com/amannn/next-intl/issues/786.
|
|
7
7
|
*/
|
|
8
|
-
export default function syncLocaleCookie(localeCookie: InitializedLocaleCookieConfig,
|
|
8
|
+
export default function syncLocaleCookie(localeCookie: InitializedLocaleCookieConfig, locale: Locale, nextLocale?: Locale): void;
|
|
@@ -47,7 +47,7 @@ export declare function compileLocalizedPathname<AppLocales extends Locales, Pat
|
|
|
47
47
|
query?: Record<string, SearchParamValue>;
|
|
48
48
|
}): UrlObject;
|
|
49
49
|
export declare function getRoute<AppLocales extends Locales>(locale: AppLocales[number], pathname: string, pathnames: Pathnames<AppLocales>): keyof Pathnames<AppLocales>;
|
|
50
|
-
export declare function getBasePath(
|
|
50
|
+
export declare function getBasePath(): string;
|
|
51
51
|
export declare function applyPathnamePrefix<AppLocales extends Locales, AppLocalePrefixMode extends LocalePrefixMode, AppPathnames extends Pathnames<AppLocales> | undefined, AppDomains extends DomainsConfig<AppLocales> | undefined>(pathname: string, locale: Locales[number], routing: Pick<ResolvedRoutingConfig<AppLocales, AppLocalePrefixMode, AppPathnames, AppDomains>, 'localePrefix' | 'domains'> & Partial<Pick<ResolvedRoutingConfig<AppLocales, AppLocalePrefixMode, AppPathnames, AppDomains>, 'defaultLocale'>>, force?: boolean): string;
|
|
52
52
|
export declare function validateReceivedConfig<AppLocales extends Locales, AppLocalePrefixMode extends LocalePrefixMode, AppPathnames extends Pathnames<AppLocales> | undefined, AppDomains extends DomainsConfig<AppLocales> | undefined>(config: Partial<Pick<ResolvedRoutingConfig<AppLocales, AppLocalePrefixMode, AppPathnames, AppDomains>, 'defaultLocale' | 'localePrefix'>>): void;
|
|
53
53
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-intl",
|
|
3
|
-
"version": "4.14.
|
|
3
|
+
"version": "4.14.5",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"author": "Jan Amann <jan@amann.work>",
|
|
6
6
|
"funding": [
|
|
@@ -130,14 +130,14 @@
|
|
|
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.
|
|
133
|
+
"icu-minify": "^4.14.5",
|
|
134
134
|
"negotiator": "^1.0.0",
|
|
135
|
-
"next-intl-swc-plugin-extractor": "4.14.
|
|
136
|
-
"use-intl": "^4.14.
|
|
135
|
+
"next-intl-swc-plugin-extractor": "4.14.5",
|
|
136
|
+
"use-intl": "^4.14.5"
|
|
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": "
|
|
142
|
+
"gitHead": "7691fca617453cbacc49e6949302954e21dee60b"
|
|
143
143
|
}
|