Skip to content

Commit

Permalink
fix(i18n): parse params and props correctly with fallback (#12709)
Browse files Browse the repository at this point in the history
Co-authored-by: Emanuele Stoppa <[email protected]>
  • Loading branch information
mtwilliams-code and ematipico authored Dec 12, 2024
1 parent 358eae8 commit e3bfd93
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 10 deletions.
5 changes: 5 additions & 0 deletions .changeset/selfish-paws-play.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fixes a bug where Astro couldn't correctly parse `params` and `props` when receiving i18n fallback URLs
9 changes: 7 additions & 2 deletions packages/astro/src/core/render/params-and-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ export async function getProps(opts: GetParamsAndPropsOptions): Promise<Props> {
base,
});

// The pathname used here comes from the server, which already encored.
if (!staticPaths.length) return {};
// The pathname used here comes from the server, which already encoded.
// Since we decided to not mess up with encoding anymore, we need to decode them back so the parameters can match
// the ones expected from the users
const params = getParams(route, decodeURI(pathname));
Expand Down Expand Up @@ -77,7 +78,11 @@ export function getParams(route: RouteData, pathname: string): Params {
if (!route.params.length) return {};
// The RegExp pattern expects a decoded string, but the pathname is encoded
// when the URL contains non-English characters.
const paramsMatch = route.pattern.exec(pathname);
const paramsMatch =
route.pattern.exec(pathname) ||
route.fallbackRoutes
.map((fallbackRoute) => fallbackRoute.pattern.exec(pathname))
.find((x) => x);
if (!paramsMatch) return {};
const params: Params = {};
route.params.forEach((key, i) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
---
// for SSR
const blogs = {
1: { content: "Hello world" },
2: { content: "Eat Something" },
3: { content: "How are you?" },
}
const id = Astro.params?.id;
const ssrContent = id && blogs[id]?.content;
// for SSG
export function getStaticPaths() {
return [
{params: {id: '1'}, props: { content: "Hello world" }},
{params: {id: '2'}, props: { content: "Eat Something" }},
{params: {id: '3'}, props: { content: "How are you?" }},
];
]
}
const { content } = Astro.props;
const { content } = Astro.props
---
<html>
<head>
<title>Astro</title>
</head>
<body>
{content}
{content || ssrContent}
</body>
</html>
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
---
const blogs = {
1: { content: "Hola mundo" },
2: { content: "Eat Something" },
3: { content: "How are you?" },
}
const id = Astro.params?.id;
const ssrContent = id && blogs[id]?.content;
export function getStaticPaths() {
return [
{params: {id: '1'}, props: { content: "Hola mundo" }},
Expand All @@ -13,6 +21,6 @@ const { content } = Astro.props;
<title>Astro</title>
</head>
<body>
{content}
{content || ssrContent}
</body>
</html>
74 changes: 70 additions & 4 deletions packages/astro/test/i18n-routing.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as cheerio from 'cheerio';
import * as assert from 'node:assert/strict';
import { after, afterEach, before, describe, it } from 'node:test';
import * as cheerio from 'cheerio';
import testAdapter from './test-adapter.js';
import { loadFixture } from './test-utils.js';

Expand Down Expand Up @@ -2000,12 +2000,14 @@ describe('Fallback rewrite dev server', () => {
root: './fixtures/i18n-routing-fallback/',
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr'],
locales: ['en', 'fr', 'es', 'it', 'pt'],
routing: {
prefixDefaultLocale: false,
},
fallback: {
fr: 'en',
it: 'en',
es: 'pt',
},
fallbackType: 'rewrite',
},
Expand All @@ -2021,6 +2023,27 @@ describe('Fallback rewrite dev server', () => {
assert.match(html, /Hello/);
// assert.fail()
});

it('should render fallback locale paths with path parameters correctly (fr)', async () => {
let response = await fixture.fetch('/fr/blog/1');
assert.equal(response.status, 200);
const text = await response.text();
assert.match(text, /Hello world/);
});

it('should render fallback locale paths with path parameters correctly (es)', async () => {
let response = await fixture.fetch('/es/blog/1');
assert.equal(response.status, 200);
const text = await response.text();
assert.match(text, /Hola mundo/);
});

it('should render fallback locale paths with query parameters correctly (it)', async () => {
let response = await fixture.fetch('/it/blog/1');
assert.equal(response.status, 200);
const text = await response.text();
assert.match(text, /Hello world/);
});
});

describe('Fallback rewrite SSG', () => {
Expand All @@ -2032,13 +2055,15 @@ describe('Fallback rewrite SSG', () => {
root: './fixtures/i18n-routing-fallback/',
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr'],
locales: ['en', 'fr', 'es', 'it', 'pt'],
routing: {
prefixDefaultLocale: false,
fallbackType: 'rewrite',
},
fallback: {
fr: 'en',
it: 'en',
es: 'pt',
},
},
});
Expand All @@ -2051,6 +2076,21 @@ describe('Fallback rewrite SSG', () => {
assert.match(html, /Hello/);
// assert.fail()
});

it('should render fallback locale paths with path parameters correctly (fr)', async () => {
const html = await fixture.readFile('/fr/blog/1/index.html');
assert.match(html, /Hello world/);
});

it('should render fallback locale paths with path parameters correctly (es)', async () => {
const html = await fixture.readFile('/es/blog/1/index.html');
assert.match(html, /Hola mundo/);
});

it('should render fallback locale paths with query parameters correctly (it)', async () => {
const html = await fixture.readFile('/it/blog/1/index.html');
assert.match(html, /Hello world/);
});
});

describe('Fallback rewrite SSR', () => {
Expand All @@ -2066,13 +2106,15 @@ describe('Fallback rewrite SSR', () => {
adapter: testAdapter(),
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr'],
locales: ['en', 'fr', 'es', 'it', 'pt'],
routing: {
prefixDefaultLocale: false,
fallbackType: 'rewrite',
},
fallback: {
fr: 'en',
it: 'en',
es: 'pt',
},
},
});
Expand All @@ -2087,4 +2129,28 @@ describe('Fallback rewrite SSR', () => {
const html = await response.text();
assert.match(html, /Hello/);
});

it('should render fallback locale paths with path parameters correctly (fr)', async () => {
let request = new Request('http://example.com/new-site/fr/blog/1');
let response = await app.render(request);
assert.equal(response.status, 200);
const text = await response.text();
assert.match(text, /Hello world/);
});

it('should render fallback locale paths with path parameters correctly (es)', async () => {
let request = new Request('http://example.com/new-site/es/blog/1');
let response = await app.render(request);
assert.equal(response.status, 200);
const text = await response.text();
assert.match(text, /Hola mundo/);
});

it('should render fallback locale paths with query parameters correctly (it)', async () => {
let request = new Request('http://example.com/new-site/it/blog/1');
let response = await app.render(request);
assert.equal(response.status, 200);
const text = await response.text();
assert.match(text, /Hello world/);
});
});

0 comments on commit e3bfd93

Please sign in to comment.