diff options
-rw-r--r-- | .changeset/ninety-nights-hug.md | 7 | ||||
-rw-r--r-- | packages/astro/src/i18n/index.ts | 13 | ||||
-rw-r--r-- | packages/astro/src/i18n/utils.ts | 19 | ||||
-rw-r--r-- | packages/astro/test/fixtures/i18n-routing-redirect-preferred-language/astro.config.mjs | 9 | ||||
-rw-r--r-- | packages/astro/test/i18n-routing.test.js | 18 |
5 files changed, 51 insertions, 15 deletions
diff --git a/.changeset/ninety-nights-hug.md b/.changeset/ninety-nights-hug.md new file mode 100644 index 000000000..aa4017497 --- /dev/null +++ b/.changeset/ninety-nights-hug.md @@ -0,0 +1,7 @@ +--- +'astro': patch +--- + +Fixes a bug where the functions `Astro.preferredLocale` and `Astro.preferredLocaleList` would return the incorrect locales +when the Astro configuration specifies a list of `codes`. Before, the functions would return the `path`, instead now the functions +return a list built from `codes`. diff --git a/packages/astro/src/i18n/index.ts b/packages/astro/src/i18n/index.ts index 73b33fa60..10d451b22 100644 --- a/packages/astro/src/i18n/index.ts +++ b/packages/astro/src/i18n/index.ts @@ -229,6 +229,18 @@ export function normalizeTheLocale(locale: string): string { * Returns an array of only locales, by picking the `code` * @param locales */ +export function getAllCodes(locales: Locales): string[] { + const result: string[] = []; + for (const loopLocale of locales) { + if (typeof loopLocale === 'string') { + result.push(loopLocale); + } else { + result.push(...loopLocale.codes); + } + } + return result +} + export function toCodes(locales: Locales): string[] { return locales.map((loopLocale) => { if (typeof loopLocale === 'string') { @@ -239,6 +251,7 @@ export function toCodes(locales: Locales): string[] { }); } + /** * It returns the array of paths * @param locales diff --git a/packages/astro/src/i18n/utils.ts b/packages/astro/src/i18n/utils.ts index 18a6f8dca..ed8ec147d 100644 --- a/packages/astro/src/i18n/utils.ts +++ b/packages/astro/src/i18n/utils.ts @@ -1,6 +1,6 @@ import type { SSRManifest } from '../core/app/types.js'; import type { AstroConfig, Locales } from '../types/public/config.js'; -import { normalizeTheLocale, toCodes } from './index.js'; +import { normalizeTheLocale, getAllCodes } from './index.js'; type BrowserLocale = { locale: string; @@ -62,7 +62,7 @@ export function parseLocale(header: string): BrowserLocale[] { } function sortAndFilterLocales(browserLocaleList: BrowserLocale[], locales: Locales) { - const normalizedLocales = toCodes(locales).map(normalizeTheLocale); + const normalizedLocales = getAllCodes(locales).map(normalizeTheLocale); return browserLocaleList .filter((browserLocale) => { if (browserLocale.locale !== '*') { @@ -96,11 +96,13 @@ export function computePreferredLocale(request: Request, locales: Locales): stri if (typeof currentLocale === 'string') { if (normalizeTheLocale(currentLocale) === normalizeTheLocale(firstResult.locale)) { result = currentLocale; + break; } } else { for (const currentCode of currentLocale.codes) { if (normalizeTheLocale(currentCode) === normalizeTheLocale(firstResult.locale)) { - result = currentLocale.path; + result = currentCode; + break; } } } @@ -119,14 +121,7 @@ export function computePreferredLocaleList(request: Request, locales: Locales): // SAFETY: bang operator is safe because checked by the previous condition if (browserLocaleList.length === 1 && browserLocaleList.at(0)!.locale === '*') { - return locales.map((locale) => { - if (typeof locale === 'string') { - return locale; - } else { - // SAFETY: codes is never empty - return locale.codes.at(0)!; - } - }); + return getAllCodes(locales); } else if (browserLocaleList.length > 0) { for (const browserLocale of browserLocaleList) { for (const loopLocale of locales) { @@ -137,7 +132,7 @@ export function computePreferredLocaleList(request: Request, locales: Locales): } else { for (const code of loopLocale.codes) { if (code === browserLocale.locale) { - result.push(loopLocale.path); + result.push(code); } } } diff --git a/packages/astro/test/fixtures/i18n-routing-redirect-preferred-language/astro.config.mjs b/packages/astro/test/fixtures/i18n-routing-redirect-preferred-language/astro.config.mjs index 259b10d07..20e815540 100644 --- a/packages/astro/test/fixtures/i18n-routing-redirect-preferred-language/astro.config.mjs +++ b/packages/astro/test/fixtures/i18n-routing-redirect-preferred-language/astro.config.mjs @@ -4,7 +4,14 @@ export default defineConfig({ i18n: { defaultLocale: 'en', locales: [ - 'en', 'pt', 'it' + 'en', + 'pt', + 'it', + { + path: "zh-Hant", + codes: ["zh-HK", "zh-TW"] + } + ] } }) diff --git a/packages/astro/test/i18n-routing.test.js b/packages/astro/test/i18n-routing.test.js index 473fc8817..a0a2eccfb 100644 --- a/packages/astro/test/i18n-routing.test.js +++ b/packages/astro/test/i18n-routing.test.js @@ -1701,6 +1701,20 @@ describe('[SSR] i18n routing', () => { assert.equal(text.includes('Locale list: en, pt, it'), true); }); + + it('should render the preferred locale when a locale is configured with codes', async () => { + let request = new Request('http://example.com/preferred-locale', { + headers: { + 'Accept-Language': 'es-SP;q=0.9,es;q=0.8,en-US;q=0.7,en;q=0.6', + }, + }); + let response = await app.render(request); + const text = await response.text(); + assert.equal(response.status, 200); + assert.equal(text.includes('Locale: es-SP'), true); + assert.equal(text.includes('Locale list: es-SP, es, en'), true); + }); + describe('in case the configured locales use underscores', () => { before(async () => { fixture = await loadFixture({ @@ -1751,8 +1765,8 @@ describe('[SSR] i18n routing', () => { let response = await app.render(request); const text = await response.text(); assert.equal(response.status, 200); - assert.equal(text.includes('Locale: spanish'), true); - assert.equal(text.includes('Locale list: spanish'), true); + assert.equal(text.includes('Locale: es'), true); + assert.equal(text.includes('Locale list: es'), true); }); }); }); |