Skip to content

Commit 82cd583

Browse files
fix(i18n): return value from preferredLocale (#13524)
* fix(i18n): return value from `preferredLocale` * revert change Co-authored-by: florian-lefebvre <[email protected]>
1 parent 32499c0 commit 82cd583

File tree

5 files changed

+51
-15
lines changed

5 files changed

+51
-15
lines changed

.changeset/ninety-nights-hug.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'astro': patch
3+
---
4+
5+
Fixes a bug where the functions `Astro.preferredLocale` and `Astro.preferredLocaleList` would return the incorrect locales
6+
when the Astro configuration specifies a list of `codes`. Before, the functions would return the `path`, instead now the functions
7+
return a list built from `codes`.

packages/astro/src/i18n/index.ts

+13
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,18 @@ export function normalizeTheLocale(locale: string): string {
229229
* Returns an array of only locales, by picking the `code`
230230
* @param locales
231231
*/
232+
export function getAllCodes(locales: Locales): string[] {
233+
const result: string[] = [];
234+
for (const loopLocale of locales) {
235+
if (typeof loopLocale === 'string') {
236+
result.push(loopLocale);
237+
} else {
238+
result.push(...loopLocale.codes);
239+
}
240+
}
241+
return result
242+
}
243+
232244
export function toCodes(locales: Locales): string[] {
233245
return locales.map((loopLocale) => {
234246
if (typeof loopLocale === 'string') {
@@ -239,6 +251,7 @@ export function toCodes(locales: Locales): string[] {
239251
});
240252
}
241253

254+
242255
/**
243256
* It returns the array of paths
244257
* @param locales

packages/astro/src/i18n/utils.ts

+7-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { SSRManifest } from '../core/app/types.js';
22
import type { AstroConfig, Locales } from '../types/public/config.js';
3-
import { normalizeTheLocale, toCodes } from './index.js';
3+
import { normalizeTheLocale, getAllCodes } from './index.js';
44

55
type BrowserLocale = {
66
locale: string;
@@ -62,7 +62,7 @@ export function parseLocale(header: string): BrowserLocale[] {
6262
}
6363

6464
function sortAndFilterLocales(browserLocaleList: BrowserLocale[], locales: Locales) {
65-
const normalizedLocales = toCodes(locales).map(normalizeTheLocale);
65+
const normalizedLocales = getAllCodes(locales).map(normalizeTheLocale);
6666
return browserLocaleList
6767
.filter((browserLocale) => {
6868
if (browserLocale.locale !== '*') {
@@ -96,11 +96,13 @@ export function computePreferredLocale(request: Request, locales: Locales): stri
9696
if (typeof currentLocale === 'string') {
9797
if (normalizeTheLocale(currentLocale) === normalizeTheLocale(firstResult.locale)) {
9898
result = currentLocale;
99+
break;
99100
}
100101
} else {
101102
for (const currentCode of currentLocale.codes) {
102103
if (normalizeTheLocale(currentCode) === normalizeTheLocale(firstResult.locale)) {
103-
result = currentLocale.path;
104+
result = currentCode;
105+
break;
104106
}
105107
}
106108
}
@@ -119,14 +121,7 @@ export function computePreferredLocaleList(request: Request, locales: Locales):
119121

120122
// SAFETY: bang operator is safe because checked by the previous condition
121123
if (browserLocaleList.length === 1 && browserLocaleList.at(0)!.locale === '*') {
122-
return locales.map((locale) => {
123-
if (typeof locale === 'string') {
124-
return locale;
125-
} else {
126-
// SAFETY: codes is never empty
127-
return locale.codes.at(0)!;
128-
}
129-
});
124+
return getAllCodes(locales);
130125
} else if (browserLocaleList.length > 0) {
131126
for (const browserLocale of browserLocaleList) {
132127
for (const loopLocale of locales) {
@@ -137,7 +132,7 @@ export function computePreferredLocaleList(request: Request, locales: Locales):
137132
} else {
138133
for (const code of loopLocale.codes) {
139134
if (code === browserLocale.locale) {
140-
result.push(loopLocale.path);
135+
result.push(code);
141136
}
142137
}
143138
}

packages/astro/test/fixtures/i18n-routing-redirect-preferred-language/astro.config.mjs

+8-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@ export default defineConfig({
44
i18n: {
55
defaultLocale: 'en',
66
locales: [
7-
'en', 'pt', 'it'
7+
'en',
8+
'pt',
9+
'it',
10+
{
11+
path: "zh-Hant",
12+
codes: ["zh-HK", "zh-TW"]
13+
}
14+
815
]
916
}
1017
})

packages/astro/test/i18n-routing.test.js

+16-2
Original file line numberDiff line numberDiff line change
@@ -1701,6 +1701,20 @@ describe('[SSR] i18n routing', () => {
17011701
assert.equal(text.includes('Locale list: en, pt, it'), true);
17021702
});
17031703

1704+
1705+
it('should render the preferred locale when a locale is configured with codes', async () => {
1706+
let request = new Request('http://example.com/preferred-locale', {
1707+
headers: {
1708+
'Accept-Language': 'es-SP;q=0.9,es;q=0.8,en-US;q=0.7,en;q=0.6',
1709+
},
1710+
});
1711+
let response = await app.render(request);
1712+
const text = await response.text();
1713+
assert.equal(response.status, 200);
1714+
assert.equal(text.includes('Locale: es-SP'), true);
1715+
assert.equal(text.includes('Locale list: es-SP, es, en'), true);
1716+
});
1717+
17041718
describe('in case the configured locales use underscores', () => {
17051719
before(async () => {
17061720
fixture = await loadFixture({
@@ -1751,8 +1765,8 @@ describe('[SSR] i18n routing', () => {
17511765
let response = await app.render(request);
17521766
const text = await response.text();
17531767
assert.equal(response.status, 200);
1754-
assert.equal(text.includes('Locale: spanish'), true);
1755-
assert.equal(text.includes('Locale list: spanish'), true);
1768+
assert.equal(text.includes('Locale: es'), true);
1769+
assert.equal(text.includes('Locale list: es'), true);
17561770
});
17571771
});
17581772
});

0 commit comments

Comments
 (0)