Skip to content

Commit 9a8a179

Browse files
bjlaaClemogdependabot[bot]paulsouchegithub-advanced-security[bot]
authored
🔖 Release 2.26.3 (#1203)
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Clément <clem.auger@hotmail.fr> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Clément <55186402+Clemog@users.noreply.github.com> Co-authored-by: Paul Souche <paul@bettercallpaul.fr> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: Benjamin Arias <12382534+bjlaa@users.noreply.github.com> Co-authored-by: Bot Incubateur Ademe <153178900+incubateur-ademe-admin@users.noreply.github.com>
1 parent 8c3278c commit 9a8a179

File tree

4 files changed

+55
-23
lines changed

4 files changed

+55
-23
lines changed

‎cypress/e2e/integration/features/i18n-middleware.cy.js‎

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,42 @@ describe('i18nMiddleware - E2E Tests', () => {
1313
cy.visit('/fr/simulateur/bilan?lang=en')
1414

1515
// Verify that URL has been redirected
16-
cy.url().should('include', '/en/simulateur/bilan')
16+
cy.url().should('include', '/en/tutoriel')
1717
cy.url().should('not.include', 'lang=en')
1818
})
1919

2020
it('should clean URL if locale is already correct', () => {
21-
cy.visit('/en/simulateur/bilan?lang=en')
21+
cy.visit('/en/fin?lang=en')
2222

2323
// Verify that lang parameter has been removed
2424
cy.url().should('not.include', 'lang=en')
25-
cy.url().should('include', '/en/simulateur/bilan')
25+
cy.url().should('include', '/en/fin')
2626
})
2727
})
2828

2929
describe('Iframe handling', () => {
3030
it('should work with iframe parameter', () => {
31-
cy.visit('/fr/simulateur/bilan?iframe=true')
31+
cy.visit('/fr/fin?iframe=true')
3232

3333
// Verify that page loads without 404 error
3434
cy.get('body').should('exist')
3535
cy.url().should('include', 'iframe=true')
3636
})
3737

38-
it('should handle iframes with lang parameter', () => {
39-
cy.visit('/fr/simulateur/bilan?iframe=true&lang=en')
38+
it('should redirect to locale-prefixed URL when using iframe and lang parameters', () => {
39+
cy.visit('/simulateur/bilan?iframe=true&lang=en')
4040

41-
// Verify that page loads
41+
// Verify that the URL has been redirected correctly
42+
cy.url().should('include', '/en/tutoriel')
43+
cy.url().should('not.include', 'lang=en')
44+
45+
// Also check that the page has loaded correctly
4246
cy.get('body').should('exist')
43-
// Iframe parameter should prevent redirection
44-
cy.url().should('include', 'iframe=true')
4547
})
4648

4749
it('should detect iframes via referer', () => {
4850
// Simulate request with referer containing iframe=true
49-
cy.visit('/fr/simulateur/bilan', {
51+
cy.visit('/fr/fin', {
5052
headers: {
5153
referer: 'https://example.com/page?iframe=true',
5254
},
@@ -58,31 +60,31 @@ describe('i18nMiddleware - E2E Tests', () => {
5860

5961
describe('URL construction with locale', () => {
6062
it('should add locale if it does not exist in path', () => {
61-
cy.visit('/simulateur/bilan?lang=en')
63+
cy.visit('/fin?lang=en')
6264

63-
cy.url().should('include', '/en/simulateur/bilan')
65+
cy.url().should('include', '/en/fin')
6466
cy.url().should('not.include', 'lang=en')
6567
})
6668

6769
it('should replace existing locale', () => {
68-
cy.visit('/fr/simulateur/bilan?lang=en')
70+
cy.visit('/fr/fin?lang=en')
6971

70-
cy.url().should('include', '/en/simulateur/bilan')
72+
cy.url().should('include', '/en/fin')
7173
cy.url().should('not.include', '/fr/')
7274
cy.url().should('not.include', 'lang=en')
7375
})
7476
})
7577

7678
describe('Cookie handling', () => {
7779
it('should set locale cookie', () => {
78-
cy.visit('/fr/simulateur/bilan?lang=en')
80+
cy.visit('/fr/fin?lang=en')
7981

8082
// Verify that cookie has been set
8183
cy.getCookie('NEXT_LOCALE').should('have.property', 'value', 'en')
8284
})
8385

8486
it('should preserve cookie during navigation', () => {
85-
cy.visit('/fr/simulateur/bilan?lang=en')
87+
cy.visit('/fr/fin?lang=en')
8688

8789
// Navigate to another page
8890
cy.visit('/en/actions')
@@ -101,9 +103,9 @@ describe('i18nMiddleware - E2E Tests', () => {
101103
})
102104

103105
it('should handle multiple parameters', () => {
104-
cy.visit('/fr/simulateur/bilan?lang=en&other=param')
106+
cy.visit('/fr/fin?lang=en&other=param')
105107

106-
cy.url().should('include', '/en/simulateur/bilan')
108+
cy.url().should('include', '/en/fin')
107109
cy.url().should('include', 'other=param')
108110
cy.url().should('not.include', 'lang=en')
109111
})

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "nosgestesclimat-site-nextjs",
33
"license": "MIT",
4-
"version": "2.26.2",
4+
"version": "2.26.3",
55
"description": "The leading open source climate footprint calculator",
66
"repository": {
77
"type": "git",

‎src/middlewares/__tests__/i18nMiddleware.test.ts‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ describe('i18nMiddleware', () => {
5757
expect(cookie?.value).toBe('en')
5858
})
5959

60-
it('should use lang parameter for iframes', async () => {
60+
it('should redirect to locale-prefixed URL for iframes with lang parameter', async () => {
6161
const request = createMockRequest(
6262
'/simulateur/bilan',
6363
{ iframe: 'true', lang: 'en' },
@@ -66,7 +66,15 @@ describe('i18nMiddleware', () => {
6666

6767
const response = await i18nMiddleware(request)
6868

69-
expect(response).toBeInstanceOf(NextResponse)
69+
// It should redirect
70+
expect(response.status).toBe(307)
71+
const location = response.headers.get('location')
72+
// The new URL should be prefixed with the locale, and keep the iframe param
73+
expect(location).toContain('/en/simulateur/bilan')
74+
expect(location).toContain('iframe=true')
75+
// The lang param should be removed
76+
expect(location).not.toContain('lang=en')
77+
// The cookie should be set
7078
expect(response.cookies.get('NEXT_LOCALE')?.value).toBe('en')
7179
})
7280

‎src/middlewares/i18nMiddleware.ts‎

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,29 @@ function setLocaleCookie(response: NextResponse, locale: string): void {
3939

4040
function i18nMiddleware(request: NextRequest) {
4141
const langParam = request.nextUrl.searchParams.get('lang')
42-
const { locales, defaultLocale } = i18nConfig
42+
const { locales } = i18nConfig
43+
44+
if (
45+
request.nextUrl.searchParams.get('iframe') &&
46+
langParam &&
47+
locales.includes(langParam)
48+
) {
49+
const newPath = buildUrlWithLocale(
50+
request.nextUrl.pathname,
51+
langParam,
52+
locales
53+
)
54+
const url = new URL(request.url)
55+
url.pathname = newPath
56+
url.searchParams.delete('lang')
57+
58+
const redirectResponse = NextResponse.redirect(url, 307)
59+
setLocaleCookie(redirectResponse, langParam)
60+
61+
return redirectResponse
62+
}
63+
64+
const { defaultLocale } = i18nConfig
4365

4466
// Check if this is an iframe request (either via iframe param or referer)
4567
const isIframeRequest =
@@ -105,7 +127,7 @@ function i18nMiddleware(request: NextRequest) {
105127
}
106128

107129
// Clean URL if locale is already correct (non-default locales)
108-
if (request.nextUrl.searchParams.has('lang')) {
130+
if (request.nextUrl.searchParams.has('lang') && !isIframeRequest) {
109131
const url = new URL(request.url)
110132
url.searchParams.delete('lang')
111133

0 commit comments

Comments
 (0)