Skip to content

Commit 7b4ea5c

Browse files
authoredMar 1, 2025
fix localeDetection false (#761)
* fix localeDetection false * add test * added comments * changeset * remove console.log
1 parent 34511ff commit 7b4ea5c

File tree

3 files changed

+78
-7
lines changed

3 files changed

+78
-7
lines changed
 

‎.changeset/fair-pots-give.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@opennextjs/aws": patch
3+
---
4+
5+
Fix path localization for the middleware when using both `localeDetection:false` and domains

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

+24-7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ function getLocaleFromCookie(cookies: Record<string, string>) {
2323
}
2424

2525
// Inspired by https://github.com/vercel/next.js/blob/6d93d652e0e7ba72d9a3b66e78746dce2069db03/packages/next/src/shared/lib/i18n/detect-domain-locale.ts#L3-L25
26+
/**
27+
* @param arg an object containing the hostname and detectedLocale
28+
* @returns The `DomainLocale` object if a domain is detected, `undefined` otherwise
29+
*/
2630
export function detectDomainLocale({
2731
hostname,
2832
detectedLocale,
@@ -31,11 +35,12 @@ export function detectDomainLocale({
3135
detectedLocale?: string;
3236
}): DomainLocale | undefined {
3337
const i18n = NextConfig.i18n;
34-
if (!i18n || i18n.localeDetection === false || !i18n.domains) {
38+
const domains = i18n?.domains;
39+
if (!domains) {
3540
return;
3641
}
3742
const lowercasedLocale = detectedLocale?.toLowerCase();
38-
for (const domain of i18n.domains) {
43+
for (const domain of domains) {
3944
// We remove the port if present
4045
const domainHostname = domain.domain.split(":", 1)[0].toLowerCase();
4146
if (
@@ -50,12 +55,21 @@ export function detectDomainLocale({
5055
}
5156
}
5257

58+
/**
59+
*
60+
* @param internalEvent
61+
* @param i18n
62+
* @returns The detected locale, if `localeDetection` is set to `false` it will return the default locale **or** the domain default locale if a domain is detected.
63+
*/
5364
export function detectLocale(
5465
internalEvent: InternalEvent,
5566
i18n: i18nConfig,
5667
): string {
68+
const domainLocale = detectDomainLocale({
69+
hostname: internalEvent.headers.host,
70+
});
5771
if (i18n.localeDetection === false) {
58-
return i18n.defaultLocale;
72+
return domainLocale?.defaultLocale ?? i18n.defaultLocale;
5973
}
6074

6175
const cookiesLocale = getLocaleFromCookie(internalEvent.cookies);
@@ -67,10 +81,7 @@ export function detectLocale(
6781
cookiesLocale,
6882
preferredLocale,
6983
defaultLocale: i18n.defaultLocale,
70-
});
71-
72-
const domainLocale = detectDomainLocale({
73-
hostname: internalEvent.headers.host,
84+
domainLocale,
7485
});
7586

7687
return (
@@ -81,11 +92,17 @@ export function detectLocale(
8192
);
8293
}
8394

95+
/**
96+
* This function is used for OpenNext internal routing to localize the path for next config rewrite/redirects/headers and the middleware
97+
* @param internalEvent
98+
* @returns The localized path
99+
*/
84100
export function localizePath(internalEvent: InternalEvent): string {
85101
const i18n = NextConfig.i18n;
86102
if (!i18n) {
87103
return internalEvent.rawPath;
88104
}
105+
// When the path is already localized we don't need to do anything
89106
if (isLocalizedPath(internalEvent.rawPath)) {
90107
return internalEvent.rawPath;
91108
}

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

+49
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,55 @@ describe("localizePath", () => {
142142

143143
expect(result).toEqual("/en/foo");
144144
});
145+
146+
it("should use default locale if localeDetection is set to false", () => {
147+
const i18nSpy = vi.spyOn(NextConfig, "i18n", "get").mockReturnValue({
148+
defaultLocale: "en",
149+
locales: ["en", "fr"],
150+
localeDetection: false,
151+
});
152+
153+
const event = createEvent({
154+
url: "http://localhost/foo",
155+
});
156+
157+
const result = localizePath(event);
158+
159+
expect(result).toEqual("/en/foo");
160+
161+
i18nSpy.mockRestore();
162+
});
163+
164+
it("should use domain default locale if localeDetection is set to false but with a domain", () => {
165+
const i18nSpy = vi.spyOn(NextConfig, "i18n", "get").mockReturnValue({
166+
defaultLocale: "en",
167+
locales: ["en", "fr"],
168+
domains: [
169+
{
170+
domain: "mydomain.com",
171+
defaultLocale: "en",
172+
},
173+
{
174+
domain: "mydomain.fr",
175+
defaultLocale: "fr",
176+
},
177+
],
178+
localeDetection: false,
179+
});
180+
181+
const event = createEvent({
182+
url: "http://mydomain.fr/foo",
183+
headers: {
184+
host: "mydomain.fr",
185+
},
186+
});
187+
188+
const result = localizePath(event);
189+
190+
expect(result).toEqual("/fr/foo");
191+
192+
i18nSpy.mockRestore();
193+
});
145194
});
146195

147196
describe("handleLocaleRedirect", () => {

0 commit comments

Comments
 (0)