Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fair-pots-give.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@opennextjs/aws": patch
---

Fix path localization for the middleware when using both `localeDetection:false` and domains
31 changes: 24 additions & 7 deletions packages/open-next/src/core/routing/i18n/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ function getLocaleFromCookie(cookies: Record<string, string>) {
}

// Inspired by https://github.com/vercel/next.js/blob/6d93d652e0e7ba72d9a3b66e78746dce2069db03/packages/next/src/shared/lib/i18n/detect-domain-locale.ts#L3-L25
/**
* @param arg an object containing the hostname and detectedLocale
* @returns The `DomainLocale` object if a domain is detected, `undefined` otherwise
*/
export function detectDomainLocale({
hostname,
detectedLocale,
Expand All @@ -31,11 +35,12 @@ export function detectDomainLocale({
detectedLocale?: string;
}): DomainLocale | undefined {
const i18n = NextConfig.i18n;
if (!i18n || i18n.localeDetection === false || !i18n.domains) {
const domains = i18n?.domains;
if (!domains) {
return;
}
const lowercasedLocale = detectedLocale?.toLowerCase();
for (const domain of i18n.domains) {
for (const domain of domains) {
// We remove the port if present
const domainHostname = domain.domain.split(":", 1)[0].toLowerCase();
if (
Expand All @@ -50,12 +55,21 @@ export function detectDomainLocale({
}
}

/**
*
* @param internalEvent
* @param i18n
* @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.
*/
export function detectLocale(
internalEvent: InternalEvent,
i18n: i18nConfig,
): string {
const domainLocale = detectDomainLocale({
hostname: internalEvent.headers.host,
});
if (i18n.localeDetection === false) {
return i18n.defaultLocale;
return domainLocale?.defaultLocale ?? i18n.defaultLocale;
}

const cookiesLocale = getLocaleFromCookie(internalEvent.cookies);
Expand All @@ -67,10 +81,7 @@ export function detectLocale(
cookiesLocale,
preferredLocale,
defaultLocale: i18n.defaultLocale,
});

const domainLocale = detectDomainLocale({
hostname: internalEvent.headers.host,
domainLocale,
});

return (
Expand All @@ -81,11 +92,17 @@ export function detectLocale(
);
}

/**
* This function is used for OpenNext internal routing to localize the path for next config rewrite/redirects/headers and the middleware
* @param internalEvent
* @returns The localized path
*/
export function localizePath(internalEvent: InternalEvent): string {
const i18n = NextConfig.i18n;
if (!i18n) {
return internalEvent.rawPath;
}
// When the path is already localized we don't need to do anything
if (isLocalizedPath(internalEvent.rawPath)) {
return internalEvent.rawPath;
}
Expand Down
50 changes: 50 additions & 0 deletions packages/tests-unit/tests/core/routing/i18n.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,55 @@ describe("localizePath", () => {

expect(result).toEqual("/en/foo");
});

it("should use default locale if localeDetection is set to false", () => {
const i18nSpy = vi.spyOn(NextConfig, "i18n", "get").mockReturnValue({
defaultLocale: "en",
locales: ["en", "fr"],
localeDetection: false,
});

const event = createEvent({
url: "http://localhost/foo",
});

const result = localizePath(event);

expect(result).toEqual("/en/foo");

i18nSpy.mockRestore();
});

it("should use domain default locale if localeDetection is set to false but with a domain", () => {
const i18nSpy = vi.spyOn(NextConfig, "i18n", "get").mockReturnValue({
defaultLocale: "en",
locales: ["en", "fr"],
domains: [
{
domain: "mydomain.com",
defaultLocale: "en",
},
{
domain: "mydomain.fr",
defaultLocale: "fr",
},
],
localeDetection: false,
});

const event = createEvent({
url: "http://mydomain.fr/foo",
headers: {
host: "mydomain.fr",
},
});

const result = localizePath(event);

expect(result).toEqual("/fr/foo");

i18nSpy.mockRestore();
});
});

describe("handleLocaleRedirect", () => {
Expand All @@ -154,6 +203,7 @@ describe("handleLocaleRedirect", () => {
});

const result = handleLocaleRedirect(event);
console.log(NextConfig.i18n);

expect(result).toMatchObject({
statusCode: 307,
Expand Down
Loading