Skip to content

Commit dc05a5a

Browse files
committed
1 parent 1d3b7e5 commit dc05a5a

2 files changed

Lines changed: 48 additions & 2 deletions

File tree

packages/open-next/src/core/routing/i18n/index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { InternalEvent, InternalResult } from "@/types/open-next";
44
import { emptyReadableStream } from "@/utils/stream.js";
55

66
import { debug } from "../../../adapters/logger.js";
7-
import { constructNextUrl } from "../util.js";
7+
import { constructNextUrl, convertToQueryString } from "../util.js";
88

99
import { acceptLanguage } from "./accept-header";
1010

@@ -139,11 +139,16 @@ export function handleLocaleRedirect(internalEvent: InternalEvent): false | Inte
139139
const defaultLocale = domainLocale?.defaultLocale ?? i18n.defaultLocale;
140140

141141
if (detectedLocale.toLowerCase() !== defaultLocale.toLowerCase()) {
142+
const nextUrl = constructNextUrl(
143+
internalEvent.url,
144+
`/${detectedLocale}${NextConfig.trailingSlash ? "/" : ""}`
145+
);
146+
const queryString = convertToQueryString(internalEvent.query);
142147
return {
143148
type: "core",
144149
statusCode: 307,
145150
headers: {
146-
Location: constructNextUrl(internalEvent.url, `/${detectedLocale}`),
151+
Location: `${nextUrl}${queryString}`,
147152
},
148153
body: emptyReadableStream(),
149154
isBase64Encoded: false,

packages/tests-unit/tests/core/routing/i18n.test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ vi.mock("@opennextjs/aws/adapters/config/index.js", () => {
1111
defaultLocale: "en",
1212
locales: ["en", "fr"],
1313
},
14+
trailingSlash: undefined,
1415
},
1516
};
1617
});
@@ -225,6 +226,46 @@ describe("handleLocaleRedirect", () => {
225226
expect(result).toBe(false);
226227
});
227228

229+
it("should redirect to the localized path with a query parameter", () => {
230+
const event = createEvent({
231+
url: "http://localhost?foo=bar",
232+
headers: {
233+
"accept-language": "fr",
234+
},
235+
});
236+
237+
const result = handleLocaleRedirect(event);
238+
239+
expect(result).toMatchObject({
240+
statusCode: 307,
241+
headers: {
242+
Location: "http://localhost/fr?foo=bar",
243+
},
244+
});
245+
});
246+
247+
it("should redirect to the localized path with a query parameter when trailingSlash is true", () => {
248+
const trailingSlashSpy = vi.spyOn(NextConfig, "trailingSlash", "get").mockReturnValue(true);
249+
250+
const event = createEvent({
251+
url: "http://localhost?foo=bar",
252+
headers: {
253+
"accept-language": "fr",
254+
},
255+
});
256+
257+
const result = handleLocaleRedirect(event);
258+
259+
expect(result).toMatchObject({
260+
statusCode: 307,
261+
headers: {
262+
Location: "http://localhost/fr/?foo=bar",
263+
},
264+
});
265+
266+
trailingSlashSpy.mockRestore();
267+
});
268+
228269
describe("using domain", () => {
229270
it("should redirect to the preferred domain if the domain is different", () => {
230271
vi.spyOn(NextConfig, "i18n", "get").mockReturnValue({

0 commit comments

Comments
 (0)