Add support for localized site section titles (#3980)

This commit is contained in:
Nolann B.
2026-03-07 20:52:13 +01:00
committed by GitHub
parent 8cb9131d83
commit d666212674
7 changed files with 45 additions and 9 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Add support for localized site section titles
+2 -2
View File
@@ -348,7 +348,7 @@
"react-dom": "catalog:",
},
"catalog": {
"@gitbook/api": "0.165.0",
"@gitbook/api": "0.166.0",
"@scalar/api-client-react": "^1.3.46",
"@tsconfig/node20": "^20.1.6",
"@tsconfig/strictest": "^2.0.6",
@@ -745,7 +745,7 @@
"@fortawesome/fontawesome-svg-core": ["@fortawesome/fontawesome-svg-core@7.1.0", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "7.1.0" } }, "sha512-fNxRUk1KhjSbnbuBxlWSnBLKLBNun52ZBTcs22H/xEEzM6Ap81ZFTQ4bZBxVQGQgVY0xugKGoRcCbaKjLQ3XZA=="],
"@gitbook/api": ["@gitbook/api@0.165.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-FzdaQUrG/XEMuUiYUPold/xPKMOYQt/wBJXK+ChQh1B10KHoQOdDPezmK56WZewNHeFHcErOERcNfgQ5MdZsfQ=="],
"@gitbook/api": ["@gitbook/api@0.166.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-65wbJ6lQ6CFJ3zzkFnBcvqUbKon/2TMmt4ujZ625w8geP+2RTte7sTAeRYUA8EIxpjyDJtgChNxgTRFMPFrlNw=="],
"@gitbook/browser-types": ["@gitbook/browser-types@workspace:packages/browser-types"],
+1 -1
View File
@@ -41,7 +41,7 @@
"catalog": {
"@tsconfig/strictest": "^2.0.6",
"@tsconfig/node20": "^20.1.6",
"@gitbook/api": "0.165.0",
"@gitbook/api": "0.166.0",
"@scalar/api-client-react": "^1.3.46",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
@@ -17,6 +17,7 @@ import { isPageIndexable, isSiteIndexable } from '@/lib/seo';
import { getResizedImageURL } from '@/lib/images';
import { resolveContentRef } from '@/lib/references';
import { getSiteSectionTitle } from '@/lib/sites';
import { tcls } from '@/lib/tailwind';
import { getPageRSSURL } from '@/routes/rss';
import { PageContextProvider } from '../PageContext';
@@ -125,6 +126,7 @@ export async function generateSitePageViewport(context: GitBookSiteContext): Pro
*/
function getSiteStructureTitle(context: GitBookSiteContext): string | null {
const { visibleSections: sections, siteSpace, visibleSiteSpaces: siteSpaces } = context;
const currentLanguage = siteSpace.space.language;
const title = [];
if (
@@ -132,7 +134,7 @@ function getSiteStructureTitle(context: GitBookSiteContext): string | null {
sections.current.default === false && // Only if the current section is not the default one
sections.list.filter((section) => section.object === 'site-section').length > 1 // Only if there are multiple sections
) {
title.push(sections.current.title);
title.push(getSiteSectionTitle(sections.current, currentLanguage));
}
if (
siteSpaces.length > 1 && // Only if there are multiple variants
@@ -1,5 +1,5 @@
import type { GitBookSiteContext, SiteSections } from '@/lib/context';
import { getSectionURL, getSiteSpaceURL } from '@/lib/sites';
import { getSectionURL, getSiteSectionTitle, getSiteSpaceURL } from '@/lib/sites';
import type { SiteSection, SiteSectionGroup, SiteSpace } from '@gitbook/api';
import assertNever from 'assert-never';
@@ -99,9 +99,10 @@ function encodeChildren(
}
function encodeSection(context: GitBookSiteContext, section: SiteSection) {
const currentLanguage = context.siteSpace.space.language;
return {
id: section.id,
title: section.title,
title: getSiteSectionTitle(section, currentLanguage),
description: section.description,
icon: section.icon,
object: section.object,
+26 -1
View File
@@ -1,5 +1,11 @@
import type { GitBookSiteContext } from '@/lib/context';
import type { SiteSection, SiteSectionGroup, SiteSpace, SiteStructure } from '@gitbook/api';
import type {
SiteSection,
SiteSectionGroup,
SiteSpace,
SiteStructure,
TranslationLanguage,
} from '@gitbook/api';
import { joinPath } from './paths';
import { flattenSectionsFromGroup } from './utils';
@@ -177,3 +183,22 @@ function findSiteSpaceByIdInSiteSpaces(
): SiteSpace | null {
return siteSpaces.find(predicate) ?? null;
}
/**
* Get the appropriate title for a siteSection.
* Uses localizedTitle if available and current language is provided, otherwise uses title.
*/
export function getSiteSectionTitle(
siteSection: SiteSection,
currentLanguage: TranslationLanguage | undefined
): string {
if (
siteSection.localizedTitle &&
currentLanguage &&
siteSection.localizedTitle[currentLanguage]
) {
return siteSection.localizedTitle[currentLanguage];
}
return siteSection.title;
}
+5 -2
View File
@@ -3,7 +3,7 @@ import { throwIfDataError } from '@/lib/data';
import type { GitBookLinker } from '@/lib/links';
import { joinPath } from '@/lib/paths';
import { type FlatPageEntry, getIndexablePages } from '@/lib/sitemap';
import { getSiteStructureSections } from '@/lib/sites';
import { getSiteSectionTitle, getSiteStructureSections } from '@/lib/sites';
import type { SiteSection, SiteSpace } from '@gitbook/api';
import assertNever from 'assert-never';
import type { ListItem, Paragraph, Root, RootContent } from 'mdast';
@@ -89,6 +89,7 @@ async function getNodesFromSections(
withMarkdownPages: boolean;
}
): Promise<RootContent[]> {
const currentLanguage = context.siteSpace.space.language;
const all = await Promise.all(
siteSections.map(async (siteSection): Promise<RootContent[]> => {
const siteSpaceNodes = await getNodesFromSiteSpaces(context, siteSection.siteSpaces, {
@@ -99,7 +100,9 @@ async function getNodesFromSections(
{
type: 'heading',
depth: 2,
children: [{ type: 'text', value: siteSection.title }],
children: [
{ type: 'text', value: getSiteSectionTitle(siteSection, currentLanguage) },
],
},
...siteSpaceNodes,
];