diff options
author | Chris Swithinbank | 2024-01-31 10:57:51 +0100 |
---|---|---|
committer | GitHub | 2024-01-31 10:57:51 +0100 |
commit | 1a642e4d74ee4c30e85bce37b41888b1eae0544a (patch) | |
tree | 7e65ab26e6d839ef0ebbf71d5fa6304dc29cf22c | |
parent | c5f4a71c69dfa820876101821c138928e5960fa6 (diff) | |
download | IT.starlight-1a642e4d74ee4c30e85bce37b41888b1eae0544a.tar.gz IT.starlight-1a642e4d74ee4c30e85bce37b41888b1eae0544a.tar.bz2 IT.starlight-1a642e4d74ee4c30e85bce37b41888b1eae0544a.zip |
Update `localizedUrl()` to handle `.html` routes correctly (#1442)
-rw-r--r-- | .changeset/hip-otters-deny.md | 5 | ||||
-rw-r--r-- | packages/starlight/__tests__/basics/localizedUrl.test.ts | 27 | ||||
-rw-r--r-- | packages/starlight/__tests__/i18n-root-locale/localizedUrl.test.ts | 84 | ||||
-rw-r--r-- | packages/starlight/__tests__/i18n/localizedUrl.test.ts | 48 | ||||
-rw-r--r-- | packages/starlight/utils/localizedUrl.ts | 22 |
5 files changed, 155 insertions, 31 deletions
diff --git a/.changeset/hip-otters-deny.md b/.changeset/hip-otters-deny.md new file mode 100644 index 00000000..81121007 --- /dev/null +++ b/.changeset/hip-otters-deny.md @@ -0,0 +1,5 @@ +--- +'@astrojs/starlight': patch +--- + +Fixes URLs in language picker for sites with `build.format: 'file'` diff --git a/packages/starlight/__tests__/basics/localizedUrl.test.ts b/packages/starlight/__tests__/basics/localizedUrl.test.ts index 0c56a291..f65529cb 100644 --- a/packages/starlight/__tests__/basics/localizedUrl.test.ts +++ b/packages/starlight/__tests__/basics/localizedUrl.test.ts @@ -1,7 +1,26 @@ -import { expect, test } from 'vitest'; +import { describe, expect, test } from 'vitest'; import { localizedUrl } from '../../utils/localizedUrl'; -test('it has no effect in a monolingual project', () => { - const url = new URL('https://example.com/en/guide/'); - expect(localizedUrl(url, undefined).href).toBe(url.href); +describe('with `build.output: "directory"`', () => { + test('it has no effect in a monolingual project', () => { + const url = new URL('https://example.com/en/guide/'); + expect(localizedUrl(url, undefined).href).toBe(url.href); + }); + + test('has no effect on index route in a monolingual project', () => { + const url = new URL('https://example.com/'); + expect(localizedUrl(url, undefined).href).toBe(url.href); + }); +}); + +describe('with `build.output: "file"`', () => { + test('it has no effect in a monolingual project', () => { + const url = new URL('https://example.com/en/guide.html'); + expect(localizedUrl(url, undefined).href).toBe(url.href); + }); + + test('has no effect on index route in a monolingual project', () => { + const url = new URL('https://example.com/index.html'); + expect(localizedUrl(url, undefined).href).toBe(url.href); + }); }); diff --git a/packages/starlight/__tests__/i18n-root-locale/localizedUrl.test.ts b/packages/starlight/__tests__/i18n-root-locale/localizedUrl.test.ts index fb1b0aac..51ed335d 100644 --- a/packages/starlight/__tests__/i18n-root-locale/localizedUrl.test.ts +++ b/packages/starlight/__tests__/i18n-root-locale/localizedUrl.test.ts @@ -1,22 +1,76 @@ -import { expect, test } from 'vitest'; +import { describe, expect, test } from 'vitest'; import { localizedUrl } from '../../utils/localizedUrl'; -test('it has no effect if locale matches', () => { - const url = new URL('https://example.com/en/guide/'); - expect(localizedUrl(url, 'en').href).toBe(url.href); -}); +describe('with `build.output: "directory"`', () => { + test('it has no effect if locale matches', () => { + const url = new URL('https://example.com/en/guide/'); + expect(localizedUrl(url, 'en').href).toBe(url.href); + }); -test('it changes locale to requested locale', () => { - const url = new URL('https://example.com/en/guide/'); - expect(localizedUrl(url, 'ar').href).toBe('https://example.com/ar/guide/'); -}); + test('it has no effect if locale matches for index', () => { + const url = new URL('https://example.com/en/'); + expect(localizedUrl(url, 'en').href).toBe(url.href); + }); + + test('it changes locale to requested locale', () => { + const url = new URL('https://example.com/en/guide/'); + expect(localizedUrl(url, 'ar').href).toBe('https://example.com/ar/guide/'); + }); -test('it can change to root locale', () => { - const url = new URL('https://example.com/en/guide/'); - expect(localizedUrl(url, undefined).href).toBe('https://example.com/guide/'); + test('it changes locale to requested locale for index', () => { + const url = new URL('https://example.com/en/'); + expect(localizedUrl(url, 'ar').href).toBe('https://example.com/ar/'); + }); + + test('it can change to root locale', () => { + const url = new URL('https://example.com/en/guide/'); + expect(localizedUrl(url, undefined).href).toBe('https://example.com/guide/'); + }); + + test('it can change from root locale', () => { + const url = new URL('https://example.com/guide/'); + expect(localizedUrl(url, 'en').href).toBe('https://example.com/en/guide/'); + }); }); -test('it can change from root locale', () => { - const url = new URL('https://example.com/guide/'); - expect(localizedUrl(url, 'en').href).toBe('https://example.com/en/guide/'); +describe('with `build.output: "file"`', () => { + test('it has no effect if locale matches', () => { + const url = new URL('https://example.com/en/guide.html'); + expect(localizedUrl(url, 'en').href).toBe(url.href); + }); + + test('it has no effect if locale matches for index', () => { + const url = new URL('https://example.com/en.html'); + expect(localizedUrl(url, 'en').href).toBe(url.href); + }); + + test('it changes locale to requested locale', () => { + const url = new URL('https://example.com/en/guide.html'); + expect(localizedUrl(url, 'ar').href).toBe('https://example.com/ar/guide.html'); + }); + + test('it changes locale to requested locale for index', () => { + const url = new URL('https://example.com/en.html'); + expect(localizedUrl(url, 'ar').href).toBe('https://example.com/ar.html'); + }); + + test('it can change to root locale', () => { + const url = new URL('https://example.com/en/guide.html'); + expect(localizedUrl(url, undefined).href).toBe('https://example.com/guide.html'); + }); + + test('it can change to root locale from index', () => { + const url = new URL('https://example.com/en.html'); + expect(localizedUrl(url, undefined).href).toBe('https://example.com/index.html'); + }); + + test('it can change from root locale', () => { + const url = new URL('https://example.com/guide.html'); + expect(localizedUrl(url, 'en').href).toBe('https://example.com/en/guide.html'); + }); + + test('it can change from root locale from index', () => { + const url = new URL('https://example.com/index.html'); + expect(localizedUrl(url, 'en').href).toBe('https://example.com/en.html'); + }); }); diff --git a/packages/starlight/__tests__/i18n/localizedUrl.test.ts b/packages/starlight/__tests__/i18n/localizedUrl.test.ts index 5bdc5e08..fb4ec2d7 100644 --- a/packages/starlight/__tests__/i18n/localizedUrl.test.ts +++ b/packages/starlight/__tests__/i18n/localizedUrl.test.ts @@ -1,12 +1,46 @@ -import { expect, test } from 'vitest'; +import { describe, expect, test } from 'vitest'; import { localizedUrl } from '../../utils/localizedUrl'; -test('it has no effect if locale matches', () => { - const url = new URL('https://example.com/en/guide/'); - expect(localizedUrl(url, 'en').href).toBe(url.href); +describe('with `build.output: "directory"`', () => { + test('it has no effect if locale matches', () => { + const url = new URL('https://example.com/en/guide/'); + expect(localizedUrl(url, 'en').href).toBe(url.href); + }); + + test('it has no effect if locale matches for index', () => { + const url = new URL('https://example.com/en/'); + expect(localizedUrl(url, 'en').href).toBe(url.href); + }); + + test('it changes locale to requested locale', () => { + const url = new URL('https://example.com/en/guide/'); + expect(localizedUrl(url, 'fr').href).toBe('https://example.com/fr/guide/'); + }); + + test('it changes locale to requested locale for index', () => { + const url = new URL('https://example.com/en/'); + expect(localizedUrl(url, 'fr').href).toBe('https://example.com/fr/'); + }); }); -test('it changes locale to requested locale', () => { - const url = new URL('https://example.com/en/guide/'); - expect(localizedUrl(url, 'fr').href).toBe('https://example.com/fr/guide/'); +describe('with `build.output: "file"`', () => { + test('it has no effect if locale matches', () => { + const url = new URL('https://example.com/en/guide.html'); + expect(localizedUrl(url, 'en').href).toBe(url.href); + }); + + test('it has no effect if locale matches for index', () => { + const url = new URL('https://example.com/en.html'); + expect(localizedUrl(url, 'en').href).toBe(url.href); + }); + + test('it changes locale to requested locale', () => { + const url = new URL('https://example.com/en/guide.html'); + expect(localizedUrl(url, 'fr').href).toBe('https://example.com/fr/guide.html'); + }); + + test('it changes locale to requested locale for index', () => { + const url = new URL('https://example.com/en.html'); + expect(localizedUrl(url, 'fr').href).toBe('https://example.com/fr.html'); + }); }); diff --git a/packages/starlight/utils/localizedUrl.ts b/packages/starlight/utils/localizedUrl.ts index c7e35255..95e35f9d 100644 --- a/packages/starlight/utils/localizedUrl.ts +++ b/packages/starlight/utils/localizedUrl.ts @@ -17,14 +17,26 @@ export function localizedUrl(url: URL, locale: string | undefined): URL { // Temporarily remove base to simplify if (hasBase) url.pathname = url.pathname.replace(base, ''); const [_leadingSlash, baseSegment] = url.pathname.split('/'); - if (baseSegment && baseSegment in config.locales) { + // Strip .html extension to handle file output builds where URL might be e.g. `/en.html` + const htmlExt = '.html'; + const isRootHtml = baseSegment?.endsWith(htmlExt); + const baseSlug = isRootHtml ? baseSegment?.slice(0, -1 * htmlExt.length) : baseSegment; + if (baseSlug && baseSlug in config.locales) { // We’re in a localized route, substitute the new locale (or strip for root lang). - url.pathname = locale - ? url.pathname.replace(baseSegment, locale) - : url.pathname.replace('/' + baseSegment, ''); + if (locale) { + url.pathname = url.pathname.replace(baseSlug, locale); + } else if (isRootHtml) { + url.pathname = '/index.html'; + } else { + url.pathname = url.pathname.replace('/' + baseSlug, ''); + } } else if (locale) { // We’re in the root language. Inject the new locale if we have one. - url.pathname = '/' + locale + url.pathname; + if (baseSegment === 'index.html') { + url.pathname = '/' + locale + '.html'; + } else { + url.pathname = '/' + locale + url.pathname; + } } // Restore base if (hasBase) url.pathname = base + url.pathname; |