diff --git a/src/content/docs/en/tutorial/0-introduction/index.mdx b/src/content/docs/en/tutorial/0-introduction/index.mdx index 77e26cd9061c8..d1f984594bd21 100644 --- a/src/content/docs/en/tutorial/0-introduction/index.mdx +++ b/src/content/docs/en/tutorial/0-introduction/index.mdx @@ -8,6 +8,9 @@ description: >- Learn the basics of Astro with a project-based tutorial. All the background knowledge you need to get started! i18nReady: true +head: + - tag: title + content: Build a blog tutorial | Docs --- import Checklist from '~/components/Checklist.astro'; import Box from '~/components/tutorial/Box.astro'; diff --git a/src/content/docs/en/tutorial/1-setup/index.mdx b/src/content/docs/en/tutorial/1-setup/index.mdx index 075b28ff39582..e2d4491df246b 100644 --- a/src/content/docs/en/tutorial/1-setup/index.mdx +++ b/src/content/docs/en/tutorial/1-setup/index.mdx @@ -8,6 +8,9 @@ description: >- Prepare your development environment, and create and deploy your first Astro site i18nReady: true +head: + - tag: title + content: 'Build a blog tutorial: Unit 1 - Setup | Docs' --- import Checklist from '~/components/Checklist.astro'; import Box from '~/components/tutorial/Box.astro'; diff --git a/src/content/docs/en/tutorial/2-pages/index.mdx b/src/content/docs/en/tutorial/2-pages/index.mdx index 58225f7b20c5b..047a954694906 100644 --- a/src/content/docs/en/tutorial/2-pages/index.mdx +++ b/src/content/docs/en/tutorial/2-pages/index.mdx @@ -6,6 +6,9 @@ description: |- Tutorial: Build your first Astro blog — Create, style, and link to pages posts on your site i18nReady: true +head: + - tag: title + content: 'Build a blog tutorial: Unit 2 - Pages | Docs' --- import Checklist from '~/components/Checklist.astro'; import Box from '~/components/tutorial/Box.astro'; diff --git a/src/content/docs/en/tutorial/3-components/index.mdx b/src/content/docs/en/tutorial/3-components/index.mdx index 3a220042d75d8..659faa9d697ea 100644 --- a/src/content/docs/en/tutorial/3-components/index.mdx +++ b/src/content/docs/en/tutorial/3-components/index.mdx @@ -6,6 +6,9 @@ description: |- Tutorial: Build your first Astro blog — Build Astro components to reuse code for common elements across your website i18nReady: true +head: + - tag: title + content: 'Build a blog tutorial: Unit 3 - Components | Docs' --- import Box from '~/components/tutorial/Box.astro'; import Checklist from '~/components/Checklist.astro'; diff --git a/src/content/docs/en/tutorial/4-layouts/index.mdx b/src/content/docs/en/tutorial/4-layouts/index.mdx index f9207df4bbe4e..1013af18fc0d3 100644 --- a/src/content/docs/en/tutorial/4-layouts/index.mdx +++ b/src/content/docs/en/tutorial/4-layouts/index.mdx @@ -8,6 +8,9 @@ description: >- Use Astro layouts to share common elements and styles across your pages and posts i18nReady: true +head: + - tag: title + content: 'Build a blog tutorial: Unit 4 - Layouts | Docs' --- import Box from '~/components/tutorial/Box.astro'; import Checklist from '~/components/Checklist.astro'; diff --git a/src/content/docs/en/tutorial/5-astro-api/index.mdx b/src/content/docs/en/tutorial/5-astro-api/index.mdx index de288e78a63b1..c139c4fd33635 100644 --- a/src/content/docs/en/tutorial/5-astro-api/index.mdx +++ b/src/content/docs/en/tutorial/5-astro-api/index.mdx @@ -8,6 +8,9 @@ description: >- Fetching and using data from project files to dynamically generate pages content and routes i18nReady: true +head: + - tag: title + content: 'Build a blog tutorial: Unit 5 - Astro API | Docs' --- import Box from '~/components/tutorial/Box.astro'; import Checklist from '~/components/Checklist.astro'; diff --git a/src/content/docs/en/tutorial/6-islands/4.mdx b/src/content/docs/en/tutorial/6-islands/4.mdx index 43b3be3f709c0..06ad6a55abe89 100644 --- a/src/content/docs/en/tutorial/6-islands/4.mdx +++ b/src/content/docs/en/tutorial/6-islands/4.mdx @@ -5,6 +5,9 @@ description: |- Tutorial: Build your first Astro blog — Convert your blog from file-based routing to content collections i18nReady: true +head: + - tag: title + content: 'Build a blog tutorial: Make a content collection | Docs' --- import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro'; import Box from '~/components/tutorial/Box.astro'; diff --git a/src/content/docs/en/tutorial/6-islands/index.mdx b/src/content/docs/en/tutorial/6-islands/index.mdx index 8c481dd09f5c9..7274291bff591 100644 --- a/src/content/docs/en/tutorial/6-islands/index.mdx +++ b/src/content/docs/en/tutorial/6-islands/index.mdx @@ -6,6 +6,9 @@ description: |- Tutorial: Build your first Astro blog — Use Astro islands to bring frontend framework components into your Astro site i18nReady: true +head: + - tag: title + content: 'Build a blog tutorial: Unit 6 - Astro Islands | Docs' --- import Box from '~/components/tutorial/Box.astro'; import Checklist from '~/components/Checklist.astro'; diff --git a/src/content/i18n-schema.ts b/src/content/i18n-schema.ts index da484d8d16d01..e116ed1da3732 100644 --- a/src/content/i18n-schema.ts +++ b/src/content/i18n-schema.ts @@ -55,6 +55,7 @@ export const AstroDocsI18nSchema = z // Tutorial Navigation 'tutorial.trackerLabel': z.string(), 'tutorial.unit': z.string(), + 'tutorial.title.prefix': z.string(), // Tutorial 'tutorial.getReady': z.string(), // Code snippet vocabulary diff --git a/src/content/i18n/en.yml b/src/content/i18n/en.yml index e08b61e1177f9..0a2ea867c6f03 100644 --- a/src/content/i18n/en.yml +++ b/src/content/i18n/en.yml @@ -51,6 +51,7 @@ progress.done: Complete # Tutorial Navigation tutorial.trackerLabel: Tutorial Tracker tutorial.unit: Unit +tutorial.title.prefix: 'Build a blog tutorial: {{title}}' # Tutorial tutorial.getReady: Get ready to… # Code snippet vocabulary diff --git a/src/content/i18n/fr.yml b/src/content/i18n/fr.yml index 826c79e7acafe..4c5ae34aa587b 100644 --- a/src/content/i18n/fr.yml +++ b/src/content/i18n/fr.yml @@ -51,6 +51,7 @@ progress.done: Terminer # Tutorial Navigation tutorial.trackerLabel: Suivi du tutoriel tutorial.unit: Unité +tutorial.title.prefix: "Tutoriel de création d'un blog : {{title}}" # Tutorial tutorial.getReady: Préparez-vous à… # Code snippet vocabulary diff --git a/src/routeData.ts b/src/routeData.ts index 96026f9d5224f..1a312bec43f06 100644 --- a/src/routeData.ts +++ b/src/routeData.ts @@ -11,7 +11,29 @@ export const onRequest = defineRouteMiddleware((context) => { }); function updateHead(context: APIContext) { - const { head, isFallback, lang } = context.locals.starlightRoute; + const { head, entry, isFallback, lang, entryMeta } = context.locals.starlightRoute; + + const title = head.find((item) => item.tag === 'title'); + const frontmatterTitle = entry.data.head.find((item) => item.tag === 'title'); + + // Update the title of tutorial entry which do not provide a custom title in their frontmatter. + if (isTutorialEntry(entry) && title && !frontmatterTitle) { + // Check if a prefix translation exists for the page content language, without any possible + // fallback. + const isPrefixTranslated = context.locals.t.exists('tutorial.title.prefix', { + lngs: [entryMeta.lang], + }); + + if (isPrefixTranslated) { + // If a prefix translation exists, use it to format the title. + title.content = context.locals.t('tutorial.title.prefix', { + title: title.content, + // Explicitly use the language based on the page content, which can be different from the + // page language for fallback pages. + lngs: [entryMeta.lang], + }); + } + } const ogImageUrl = getOgImageUrl(context.url.pathname, !!isFallback); const imageSrc = ogImageUrl ?? '/default-og-image.png'; @@ -40,7 +62,7 @@ function updateHead(context: APIContext) { function updateTutorialPagination(starlightRoute: StarlightRouteData) { const { entry, locale, pagination } = starlightRoute; - if (entry.id.split('/')[1] !== 'tutorial') return; + if (!isTutorialEntry(entry)) return; const tutorialPages = getTutorialPages(pages, locale!); const i = tutorialPages.findIndex((p) => p.id === entry.id); @@ -71,3 +93,7 @@ function updateTutorialPagination(starlightRoute: StarlightRouteData) { }; } } + +function isTutorialEntry(entry: StarlightRouteData['entry']) { + return entry.id.split('/')[1] === 'tutorial'; +}