summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiDeoo2024-11-01 16:03:11 +0100
committerGitHub2024-11-01 16:03:11 +0100
commit07673c80114021a269065e451e660337237f76e1 (patch)
tree2671a70e392821287bcb480d8f5ed1b1357b530d
parentbf42300e76241a2df888dc458c59a7478a8b2d61 (diff)
downloadIT.starlight-07673c80114021a269065e451e660337237f76e1.tar.gz
IT.starlight-07673c80114021a269065e451e660337237f76e1.tar.bz2
IT.starlight-07673c80114021a269065e451e660337237f76e1.zip
Fix invalid locale issue (#2548)
* fix: fallback to default locale in project without a root locale for pages not matching the default locale slug * Update changeset * refactor: remove duplicated `slugToLocale()` --------- Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
-rw-r--r--.changeset/great-toys-train.md5
-rw-r--r--packages/starlight/__tests__/i18n-non-root-single-locale/routing.test.ts21
-rw-r--r--packages/starlight/__tests__/i18n/routing.test.ts10
-rw-r--r--packages/starlight/integrations/shared/pathToLocale.ts14
-rw-r--r--packages/starlight/integrations/shared/slugToLocale.ts18
-rw-r--r--packages/starlight/utils/slugs.ts6
6 files changed, 49 insertions, 25 deletions
diff --git a/.changeset/great-toys-train.md b/.changeset/great-toys-train.md
new file mode 100644
index 00000000..0bef54b1
--- /dev/null
+++ b/.changeset/great-toys-train.md
@@ -0,0 +1,5 @@
+---
+'@astrojs/starlight': patch
+---
+
+Fixes a URL localization edge case. In projects without a root locale configured, slugs without a locale prefix did not fall back to the default locale as expected.
diff --git a/packages/starlight/__tests__/i18n-non-root-single-locale/routing.test.ts b/packages/starlight/__tests__/i18n-non-root-single-locale/routing.test.ts
index 5eae14d8..fae14a98 100644
--- a/packages/starlight/__tests__/i18n-non-root-single-locale/routing.test.ts
+++ b/packages/starlight/__tests__/i18n-non-root-single-locale/routing.test.ts
@@ -7,6 +7,7 @@ vi.mock('astro:content', async () =>
['fr/index.mdx', { title: 'Accueil' }],
// @ts-expect-error — Using a slug not present in Starlight docs site
['en/index.mdx', { title: 'Home page' }],
+ ['404.md', { title: '404' }],
],
})
);
@@ -17,16 +18,16 @@ test('route slugs are normalized', () => {
});
test('routes for the configured locale have locale data added', () => {
- for (const route of routes) {
- if (route.id.startsWith('fr')) {
- expect(route.lang).toBe('fr-CA');
- expect(route.dir).toBe('ltr');
- expect(route.locale).toBe('fr');
- } else {
- expect(route.lang).toBe('fr-CA');
- expect(route.dir).toBe('ltr');
- expect(route.locale).toBeUndefined();
- }
+ expect(routes[0]?.lang).toBe('fr-CA');
+ expect(routes[0]?.dir).toBe('ltr');
+ expect(routes[0]?.locale).toBe('fr');
+});
+
+test('routes not matching the configured locale fall back to the default locale', () => {
+ for (const route of routes.slice(1)) {
+ expect(route.lang).toBe('fr-CA');
+ expect(route.dir).toBe('ltr');
+ expect(route.locale).toBe('fr');
}
});
diff --git a/packages/starlight/__tests__/i18n/routing.test.ts b/packages/starlight/__tests__/i18n/routing.test.ts
index b854794b..8c025e2c 100644
--- a/packages/starlight/__tests__/i18n/routing.test.ts
+++ b/packages/starlight/__tests__/i18n/routing.test.ts
@@ -14,6 +14,8 @@ vi.mock('astro:content', async () =>
['en/guides/authoring-content.md', { title: 'Création de contenu en Markdown' }],
// @ts-expect-error — Using a slug not present in Starlight docs site
['en/404.md', { title: 'Page introuvable' }],
+ ['it/index.mdx', { title: 'Pagina iniziale' }],
+ ['404.md', { title: '404' }],
],
})
);
@@ -42,6 +44,14 @@ test('routes have locale data added', () => {
expect(lang).toBe('fr');
expect(dir).toBe('ltr');
expect(locale).toBe('fr');
+ } else if (id.startsWith('pt-br')) {
+ expect(lang).toBe('pt-BR');
+ expect(dir).toBe('ltr');
+ expect(locale).toBe('pt-br');
+ } else {
+ expect(lang).toBe('en-US');
+ expect(dir).toBe('ltr');
+ expect(locale).toBe('en');
}
}
});
diff --git a/packages/starlight/integrations/shared/pathToLocale.ts b/packages/starlight/integrations/shared/pathToLocale.ts
index 5c229a47..2ecb997c 100644
--- a/packages/starlight/integrations/shared/pathToLocale.ts
+++ b/packages/starlight/integrations/shared/pathToLocale.ts
@@ -1,14 +1,6 @@
import type { AstroConfig } from 'astro';
import type { StarlightConfig } from '../../types';
-
-function slugToLocale(
- slug: string | undefined,
- localesConfig: StarlightConfig['locales']
-): string | undefined {
- const locales = Object.keys(localesConfig || {});
- const baseSegment = slug?.split('/')[0];
- return baseSegment && locales.includes(baseSegment) ? baseSegment : undefined;
-}
+import { slugToLocale } from './slugToLocale';
/** Get current locale from the full file path. */
export function pathToLocale(
@@ -17,7 +9,7 @@ export function pathToLocale(
starlightConfig,
astroConfig,
}: {
- starlightConfig: { locales: StarlightConfig['locales'] };
+ starlightConfig: Pick<StarlightConfig, 'defaultLocale' | 'locales'>;
astroConfig: { root: AstroConfig['root']; srcDir: AstroConfig['srcDir'] };
}
): string | undefined {
@@ -31,5 +23,5 @@ export function pathToLocale(
// Strip docs path leaving only content collection file ID.
// Example: /Users/houston/repo/src/content/docs/en/guide.md => en/guide.md
const slug = path?.replace(docsDir.pathname, '');
- return slugToLocale(slug, starlightConfig.locales);
+ return slugToLocale(slug, starlightConfig);
}
diff --git a/packages/starlight/integrations/shared/slugToLocale.ts b/packages/starlight/integrations/shared/slugToLocale.ts
new file mode 100644
index 00000000..69e1f3bc
--- /dev/null
+++ b/packages/starlight/integrations/shared/slugToLocale.ts
@@ -0,0 +1,18 @@
+import type { StarlightConfig } from '../../types';
+
+/**
+ * Get the “locale” of a slug. This is the base path at which a language is served.
+ * For example, if French docs are in `src/content/docs/french/`, the locale is `french`.
+ * Root locale slugs will return `undefined`.
+ * @param slug A collection entry slug
+ */
+export function slugToLocale(
+ slug: string | undefined,
+ config: Pick<StarlightConfig, 'defaultLocale' | 'locales'>
+): string | undefined {
+ const localesConfig = config.locales ?? {};
+ const baseSegment = slug?.split('/')[0];
+ if (baseSegment && localesConfig[baseSegment]) return baseSegment;
+ if (!localesConfig.root) return config.defaultLocale.locale;
+ return undefined;
+}
diff --git a/packages/starlight/utils/slugs.ts b/packages/starlight/utils/slugs.ts
index afe971ba..e74d6841 100644
--- a/packages/starlight/utils/slugs.ts
+++ b/packages/starlight/utils/slugs.ts
@@ -1,6 +1,7 @@
import config from 'virtual:starlight/user-config';
import { BuiltInDefaultLocale } from './i18n';
import { stripTrailingSlash } from './path';
+import { slugToLocale as getLocaleFromSlug } from '../integrations/shared/slugToLocale';
export interface LocaleData {
/** Writing direction. */
@@ -18,10 +19,7 @@ export interface LocaleData {
* @param slug A collection entry slug
*/
function slugToLocale(slug: string): string | undefined {
- const locales = Object.keys(config.locales || {});
- const baseSegment = slug.split('/')[0];
- if (baseSegment && locales.includes(baseSegment)) return baseSegment;
- return undefined;
+ return getLocaleFromSlug(slug, config);
}
/** Get locale information for a given slug. */