From 0dd29299d67c0d5343ebb0facac35b06fbbe276a Mon Sep 17 00:00:00 2001 From: Jan Amann Date: Wed, 10 Sep 2025 16:51:57 +0200 Subject: [PATCH] fix: Avoid double-encoding of already encoded params --- packages/next-intl/.size-limit.ts | 2 +- .../src/navigation/createNavigation.test.tsx | 18 ++++++++++++++++++ .../next-intl/src/navigation/shared/utils.tsx | 5 +---- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/next-intl/.size-limit.ts b/packages/next-intl/.size-limit.ts index 71ddc43f7..18530be5b 100644 --- a/packages/next-intl/.size-limit.ts +++ b/packages/next-intl/.size-limit.ts @@ -15,7 +15,7 @@ const config: SizeLimitConfig = [ { name: "import * from 'next-intl' (react-server)", path: 'dist/esm/production/index.react-server.js', - limit: '14.095 KB' + limit: '14.105 KB' }, { name: "import {createNavigation} from 'next-intl/navigation' (react-client)", diff --git a/packages/next-intl/src/navigation/createNavigation.test.tsx b/packages/next-intl/src/navigation/createNavigation.test.tsx index 97d2c1409..a83b38387 100644 --- a/packages/next-intl/src/navigation/createNavigation.test.tsx +++ b/packages/next-intl/src/navigation/createNavigation.test.tsx @@ -560,6 +560,24 @@ describe.each([ ); }); + it("doesn't double-encode already encoded params", () => { + const markup = renderToString( + + Create + + ); + expect(markup).toContain('href="/en/news/launch%20%2F%20party-3"'); + }); + it('handles relative pathnames', () => { // @ts-expect-error -- Validation is still on const markup = renderToString(Test); diff --git a/packages/next-intl/src/navigation/shared/utils.tsx b/packages/next-intl/src/navigation/shared/utils.tsx index 8b44c71e1..5ce4e5fc9 100644 --- a/packages/next-intl/src/navigation/shared/utils.tsx +++ b/packages/next-intl/src/navigation/shared/utils.tsx @@ -206,10 +206,7 @@ function encodePathname(pathname: string) { // // Therefore, the bottom line is that next-intl should take care of encoding non-ASCII // characters in all cases, but can rely on `new URL()` to not double-encode characters. - return pathname - .split('/') - .map((segment) => encodeURIComponent(segment)) - .join('/'); + return new URL(pathname, 'http://l').pathname; } export function getRoute(