diff --git a/.changeset/sweet-owls-trade.md b/.changeset/sweet-owls-trade.md new file mode 100644 index 000000000000..625b315e2c07 --- /dev/null +++ b/.changeset/sweet-owls-trade.md @@ -0,0 +1,5 @@ +--- +"astro": patch +--- + +Allow i18n routing utilities like getRelativeLocaleUrl to also get the default local path when redirectToDefaultLocale is false diff --git a/packages/astro/src/i18n/index.ts b/packages/astro/src/i18n/index.ts index a575dfa97316..5a44d084092b 100644 --- a/packages/astro/src/i18n/index.ts +++ b/packages/astro/src/i18n/index.ts @@ -58,7 +58,7 @@ export function getLocaleRelativeUrl({ } const pathsToJoin = [base, prependWith]; const normalizedLocale = normalizeLocale ? normalizeTheLocale(codeToUse) : codeToUse; - if (routing === 'pathname-prefix-always') { + if (routing === 'pathname-prefix-always' || routing === 'pathname-prefix-always-no-redirect') { pathsToJoin.push(normalizedLocale); } else if (locale !== defaultLocale) { pathsToJoin.push(normalizedLocale); @@ -109,7 +109,7 @@ export function getLocaleRelativeUrlList({ const pathsToJoin = [base, prependWith]; const normalizedLocale = normalizeLocale ? normalizeTheLocale(locale) : locale; - if (routing === 'pathname-prefix-always') { + if (routing === 'pathname-prefix-always' || routing === 'pathname-prefix-always-no-redirect') { pathsToJoin.push(normalizedLocale); } else if (locale !== defaultLocale) { pathsToJoin.push(normalizedLocale); diff --git a/packages/astro/test/units/i18n/astro_i18n.test.js b/packages/astro/test/units/i18n/astro_i18n.test.js index c9d7615429f6..011193accdeb 100644 --- a/packages/astro/test/units/i18n/astro_i18n.test.js +++ b/packages/astro/test/units/i18n/astro_i18n.test.js @@ -351,6 +351,83 @@ describe('getLocaleRelativeUrl', () => { }) ).to.throw; }); + + it('should return the default locale when routing strategy is [pathname-prefix-always-no-redirect]', () => { + /** + * + * @type {import("../../../dist/@types").AstroUserConfig} + */ + const config = { + base: '/blog', + experimental: { + i18n: { + defaultLocale: 'en', + locales: ['en', 'es', 'en_US', 'en_AU'], + routing: 'pathname-prefix-always-no-redirect', + }, + }, + }; + + // directory format + expect( + getLocaleRelativeUrl({ + locale: 'en', + base: '/blog/', + trailingSlash: 'always', + format: 'directory', + ...config.experimental.i18n, + }) + ).to.eq('/blog/en/'); + expect( + getLocaleRelativeUrl({ + locale: 'es', + base: '/blog/', + ...config.experimental.i18n, + trailingSlash: 'always', + format: 'directory', + }) + ).to.eq('/blog/es/'); + + expect( + getLocaleRelativeUrl({ + locale: 'en_US', + base: '/blog/', + ...config.experimental.i18n, + trailingSlash: 'always', + format: 'directory', + }) + ).to.throw; + + // file format + expect( + getLocaleRelativeUrl({ + locale: 'en', + base: '/blog/', + ...config.experimental.i18n, + trailingSlash: 'always', + format: 'file', + }) + ).to.eq('/blog/en/'); + expect( + getLocaleRelativeUrl({ + locale: 'es', + base: '/blog/', + ...config.experimental.i18n, + trailingSlash: 'always', + format: 'file', + }) + ).to.eq('/blog/es/'); + + expect( + getLocaleRelativeUrl({ + locale: 'en_US', + base: '/blog/', + ...config.experimental.i18n, + trailingSlash: 'always', + format: 'file', + }) + ).to.throw; + }); }); describe('getLocaleRelativeUrlList', () => { @@ -545,6 +622,32 @@ describe('getLocaleRelativeUrlList', () => { }) ).to.have.members(['/blog/en', '/blog/en_US', '/blog/es']); }); + + it('should retrieve the correct list of base URL with locales [format: directory, trailingSlash: never, routingStategy: pathname-prefix-always-no-redirect]', () => { + /** + * + * @type {import("../../../dist/@types").AstroUserConfig} + */ + const config = { + experimental: { + i18n: { + defaultLocale: 'en', + locales: ['en', 'en_US', 'es'], + routing: 'pathname-prefix-always-no-redirect', + }, + }, + }; + // directory format + expect( + getLocaleRelativeUrlList({ + locale: 'en', + base: '/blog', + ...config.experimental.i18n, + trailingSlash: 'never', + format: 'directory', + }) + ).to.have.members(['/blog/en', '/blog/en_US', '/blog/es']); + }); }); describe('getLocaleAbsoluteUrl', () => { @@ -911,6 +1014,89 @@ describe('getLocaleAbsoluteUrl', () => { }) ).to.throw; }); + + it('should return the default locale when routing strategy is [pathname-prefix-always-no-redirect]', () => { + /** + * + * @type {import("../../../dist/@types").AstroUserConfig} + */ + const config = { + base: '/blog', + experimental: { + i18n: { + defaultLocale: 'en', + locales: ['en', 'es', 'en_US', 'en_AU'], + routing: 'pathname-prefix-always-no-redirect', + }, + }, + }; + + // directory format + expect( + getLocaleAbsoluteUrl({ + locale: 'en', + base: '/blog/', + trailingSlash: 'always', + site: 'https://example.com', + format: 'directory', + ...config.experimental.i18n, + }) + ).to.eq('https://example.com/blog/en/'); + expect( + getLocaleAbsoluteUrl({ + locale: 'es', + base: '/blog/', + ...config.experimental.i18n, + site: 'https://example.com', + trailingSlash: 'always', + format: 'directory', + }) + ).to.eq('https://example.com/blog/es/'); + + expect( + getLocaleAbsoluteUrl({ + locale: 'en_US', + base: '/blog/', + ...config.experimental.i18n, + site: 'https://example.com', + trailingSlash: 'always', + format: 'directory', + }) + ).to.throw; + + // file format + expect( + getLocaleAbsoluteUrl({ + locale: 'en', + base: '/blog/', + ...config.experimental.i18n, + site: 'https://example.com', + trailingSlash: 'always', + format: 'file', + }) + ).to.eq('https://example.com/blog/en/'); + expect( + getLocaleAbsoluteUrl({ + locale: 'es', + base: '/blog/', + ...config.experimental.i18n, + site: 'https://example.com', + trailingSlash: 'always', + format: 'file', + }) + ).to.eq('https://example.com/blog/es/'); + + expect( + getLocaleAbsoluteUrl({ + locale: 'en_US', + base: '/blog/', + ...config.experimental.i18n, + site: 'https://example.com', + trailingSlash: 'always', + format: 'file', + }) + ).to.throw; + }); }); describe('getLocaleAbsoluteUrlList', () => { @@ -1142,6 +1328,37 @@ describe('getLocaleAbsoluteUrlList', () => { 'https://example.com/blog/es/', ]); }); + + it('should retrieve the correct list of base URL with locales [format: directory, trailingSlash: ignore, routingStategy: pathname-prefix-always-no-redirect]', () => { + /** + * + * @type {import("../../../dist/@types").AstroUserConfig} + */ + const config = { + experimental: { + i18n: { + defaultLocale: 'en', + locales: ['en', 'en_US', 'es'], + routing: 'pathname-prefix-always-no-redirect', + }, + }, + }; + // directory format + expect( + getLocaleAbsoluteUrlList({ + locale: 'en', + base: '/blog/', + ...config.experimental.i18n, + trailingSlash: 'ignore', + format: 'directory', + site: 'https://example.com', + }) + ).to.have.members([ + 'https://example.com/blog/en/', + 'https://example.com/blog/en_US/', + 'https://example.com/blog/es/', + ]); + }); }); describe('parse accept-header', () => {