diff --git a/.changeset/chilly-otters-beam.md b/.changeset/chilly-otters-beam.md new file mode 100644 index 000000000..77341e6bf --- /dev/null +++ b/.changeset/chilly-otters-beam.md @@ -0,0 +1,5 @@ +--- +"@gitbook/colors": patch +--- + +Fix return type for `colorContrast` diff --git a/.changeset/red-countries-confess.md b/.changeset/red-countries-confess.md new file mode 100644 index 000000000..e334b3280 --- /dev/null +++ b/.changeset/red-countries-confess.md @@ -0,0 +1,5 @@ +--- +"gitbook": patch +--- + +Use space language as source of truth for UI locale diff --git a/packages/colors/src/transformations.ts b/packages/colors/src/transformations.ts index 82d09e011..e6773039c 100644 --- a/packages/colors/src/transformations.ts +++ b/packages/colors/src/transformations.ts @@ -419,7 +419,10 @@ export function dpsContrast(a: RGBColor, b: RGBColor) { return contrast < 7.5 ? 0 : contrast; } -export function colorContrast(background: string, foreground: string[] = [LIGHT_BASE, DARK_BASE]) { +export function colorContrast( + background: string, + foreground: string[] = [LIGHT_BASE, DARK_BASE] +): string { const bg = hexToRgbArray(background); const best: { color?: RGBColor; contrast: number } = { @@ -436,5 +439,5 @@ export function colorContrast(background: string, foreground: string[] = [LIGHT_ } } - return best.color ? rgbArrayToHex(best.color) : foreground[0]; + return best.color ? rgbArrayToHex(best.color) : foreground[0] || LIGHT_BASE; } diff --git a/packages/gitbook/src/app/sites/dynamic/[mode]/[siteURL]/[siteData]/(content)/layout.tsx b/packages/gitbook/src/app/sites/dynamic/[mode]/[siteURL]/[siteData]/(content)/layout.tsx index a8fd4e551..eea0f8516 100644 --- a/packages/gitbook/src/app/sites/dynamic/[mode]/[siteURL]/[siteData]/(content)/layout.tsx +++ b/packages/gitbook/src/app/sites/dynamic/[mode]/[siteURL]/[siteData]/(content)/layout.tsx @@ -22,7 +22,7 @@ export default async function SiteDynamicLayout({ const withTracking = shouldTrackEvents(await headers()); return ( - + + @@ -102,7 +102,7 @@ function DescriptionForMCPToolCall(props: { }) { const { toolCall, context } = props; - const language = getSpaceLanguage(context.customization); + const language = getSpaceLanguage(context); return (

@@ -130,7 +130,7 @@ async function DescriptionForSearchToolCall(props: { }) { const { toolCall, context } = props; - const language = getSpaceLanguage(context.customization); + const language = getSpaceLanguage(context); // Resolve all hrefs for search results in parallel const searchResultsWithHrefs = await Promise.all( @@ -241,7 +241,7 @@ function DescriptionForGetPagesToolCall(props: { }) { const { toolCall, context } = props; - const language = getSpaceLanguage(context.customization); + const language = getSpaceLanguage(context); return (

diff --git a/packages/gitbook/src/components/DocumentView/InlineLink/InlineLink.tsx b/packages/gitbook/src/components/DocumentView/InlineLink/InlineLink.tsx index 33e730403..e0869e3e9 100644 --- a/packages/gitbook/src/components/DocumentView/InlineLink/InlineLink.tsx +++ b/packages/gitbook/src/components/DocumentView/InlineLink/InlineLink.tsx @@ -20,10 +20,7 @@ export async function InlineLink(props: InlineProps) { : null; const { contentContext } = context; - const language = - contentContext && 'customization' in contentContext - ? getSpaceLanguage(contentContext.customization) - : languages.en; + const language = contentContext ? getSpaceLanguage(contentContext) : languages.en; if (!contentContext || !resolved) { return ( diff --git a/packages/gitbook/src/components/DocumentView/OpenAPI/context.tsx b/packages/gitbook/src/components/DocumentView/OpenAPI/context.tsx index 2dc088f24..70be2eb45 100644 --- a/packages/gitbook/src/components/DocumentView/OpenAPI/context.tsx +++ b/packages/gitbook/src/components/DocumentView/OpenAPI/context.tsx @@ -11,7 +11,7 @@ import { Heading } from '../Heading'; import './scalar.css'; import './style.css'; -import { DEFAULT_LOCALE, getCustomizationLocale } from '@/intl/server'; +import { DEFAULT_LOCALE, getSpaceLocale } from '@/intl/server'; import type { GitBookAnyContext } from '@/lib/context'; import type { AnyOpenAPIOperationsBlock, @@ -30,10 +30,7 @@ export function getOpenAPIContext(args: { const { props, specUrl, context } = args; const { block } = props; - const customization = context && 'customization' in context ? context.customization : null; - const customizationLocale = customization - ? getCustomizationLocale(customization) - : DEFAULT_LOCALE; + const customizationLocale = context ? getSpaceLocale(context) : DEFAULT_LOCALE; const locale = checkIsValidLocale(customizationLocale) ? customizationLocale : DEFAULT_LOCALE; return { diff --git a/packages/gitbook/src/components/Embeddable/EmbeddableRootLayout.tsx b/packages/gitbook/src/components/Embeddable/EmbeddableRootLayout.tsx index 3e2ecd1ff..fec1269d4 100644 --- a/packages/gitbook/src/components/Embeddable/EmbeddableRootLayout.tsx +++ b/packages/gitbook/src/components/Embeddable/EmbeddableRootLayout.tsx @@ -21,7 +21,7 @@ export async function EmbeddableRootLayout({ children, }: React.PropsWithChildren) { return ( - + diff --git a/packages/gitbook/src/components/PDF/PDFPage.tsx b/packages/gitbook/src/components/PDF/PDFPage.tsx index d29790f25..3918283c1 100644 --- a/packages/gitbook/src/components/PDF/PDFPage.tsx +++ b/packages/gitbook/src/components/PDF/PDFPage.tsx @@ -57,7 +57,7 @@ export async function PDFPage(props: { const customization = 'customization' in baseContext ? baseContext.customization : defaultCustomization(); - const language = getSpaceLanguage(customization); + const language = getSpaceLanguage(baseContext); // Compute the pages to render const { pages, total } = selectPages(baseContext.revision.pages, pdfParams); @@ -149,8 +149,7 @@ export async function PDFPage(props: { trademark={ customization.trademark.enabled ? ( ) : null diff --git a/packages/gitbook/src/components/PDF/PDFRootLayout.tsx b/packages/gitbook/src/components/PDF/PDFRootLayout.tsx index 8b290e2d1..498adbeb8 100644 --- a/packages/gitbook/src/components/PDF/PDFRootLayout.tsx +++ b/packages/gitbook/src/components/PDF/PDFRootLayout.tsx @@ -1,6 +1,5 @@ import { CustomizationRootLayout } from '@/components/RootLayout'; import type { GitBookSiteContext, GitBookSpaceContext } from '@/lib/context'; -import { defaultCustomization } from '@/lib/utils'; import { CustomizationThemeMode } from '@gitbook/api'; /** @@ -13,12 +12,7 @@ export async function PDFRootLayout(props: { const { context, children } = props; return ( - + {children} ); diff --git a/packages/gitbook/src/components/PageAside/PageAside.tsx b/packages/gitbook/src/components/PageAside/PageAside.tsx index 3ab7b2220..bc0570c41 100644 --- a/packages/gitbook/src/components/PageAside/PageAside.tsx +++ b/packages/gitbook/src/components/PageAside/PageAside.tsx @@ -128,7 +128,7 @@ export function PageAside(props: { function PageAsideHeader(props: { context: GitBookSiteContext }) { const { context } = props; - const language = getSpaceLanguage(context.customization); + const language = getSpaceLanguage(context); return (

{ const rgbValue = hexToRgb(value); // Check the original hex value - // @ts-expect-error const contrastValue = withContrast ? hexToRgb(colorContrast(value)) : undefined; // Add contrast if needed return `--${name}-${key}: ${rgbValue}; ${ contrastValue ? `--contrast-${name}-${key}: ${contrastValue};` : '' diff --git a/packages/gitbook/src/components/TableOfContents/TableOfContents.tsx b/packages/gitbook/src/components/TableOfContents/TableOfContents.tsx index 426c6e9cb..9afcc33d1 100644 --- a/packages/gitbook/src/components/TableOfContents/TableOfContents.tsx +++ b/packages/gitbook/src/components/TableOfContents/TableOfContents.tsx @@ -16,7 +16,7 @@ export async function TableOfContents(props: { innerHeader?: React.ReactNode; // Displayed outside the scrollable TOC, directly above the page list }) { const { innerHeader, context, header } = props; - const { space, customization, revision } = context; + const { customization, revision } = context; const pages = await encodeClientTableOfContents(context, revision.pages, revision.pages); @@ -115,8 +115,7 @@ export async function TableOfContents(props: { /> {customization.trademark.enabled ? ( ) : null} diff --git a/packages/gitbook/src/components/TableOfContents/Trademark.tsx b/packages/gitbook/src/components/TableOfContents/Trademark.tsx index 487568555..bd077d84c 100644 --- a/packages/gitbook/src/components/TableOfContents/Trademark.tsx +++ b/packages/gitbook/src/components/TableOfContents/Trademark.tsx @@ -1,21 +1,17 @@ -import type { - SiteCustomizationSettings, - SiteInsightsTrademarkPlacement, - Space, -} from '@gitbook/api'; +import type { SiteInsightsTrademarkPlacement } from '@gitbook/api'; import { Icon } from '@gitbook/icons'; import { getSpaceLanguage, t } from '@/intl/server'; import { tcls } from '@/lib/tailwind'; +import type { GitBookSpaceContext } from '@/lib/context'; import { Link } from '../primitives'; /** * Trademark link to the GitBook. */ export function Trademark(props: { - space: Space; - customization: SiteCustomizationSettings; + context: GitBookSpaceContext; placement: SiteInsightsTrademarkPlacement; }) { return ( @@ -71,12 +67,12 @@ export function Trademark(props: { * Trademark link to the GitBook. */ export function TrademarkLink(props: { - space: Space; - customization: SiteCustomizationSettings; + context: GitBookSpaceContext; placement: SiteInsightsTrademarkPlacement; }) { - const { space, customization, placement } = props; - const language = getSpaceLanguage(customization); + const { context, placement } = props; + const { space } = context; + const language = getSpaceLanguage(context); const url = new URL('https://www.gitbook.com'); url.searchParams.set('utm_source', 'content'); diff --git a/packages/gitbook/src/intl/server.ts b/packages/gitbook/src/intl/server.ts index b13076f41..a6ed78a6c 100644 --- a/packages/gitbook/src/intl/server.ts +++ b/packages/gitbook/src/intl/server.ts @@ -1,25 +1,44 @@ -import type { SiteCustomizationSettings } from '@gitbook/api'; - +import type { GitBookAnyContext } from '@/lib/context'; import { type TranslationLanguage, languages } from './translations'; export * from './translate'; -export const DEFAULT_LOCALE = 'en'; +type TranslationLocale = keyof typeof languages; + +export const DEFAULT_LOCALE = 'en' satisfies TranslationLocale; /** - * Get the locale of the customization. + * Get the locale to use for a space. */ -export function getCustomizationLocale(customization: SiteCustomizationSettings): string { - return customization.internationalization.locale; +export function getSpaceLocale(context: GitBookAnyContext): TranslationLocale { + const { space } = context; + const customization = 'site' in context ? context.customization : null; + + // If the language is configured in the space, use it in priority + if (space.language) { + if (checkIsValidLocale(space.language)) { + return space.language; + } + return DEFAULT_LOCALE; + } + + // Otherwise fallback to the deprecated customization settings + if (customization) { + return checkIsValidLocale(customization.internationalization.locale) + ? customization.internationalization.locale + : DEFAULT_LOCALE; + } + + return DEFAULT_LOCALE; } /** * Create the translation context for a space to use in the server components. */ -export function getSpaceLanguage(customization: SiteCustomizationSettings): TranslationLanguage { +export function getSpaceLanguage(context: GitBookAnyContext): TranslationLanguage { const fallback = languages[DEFAULT_LOCALE]; - const locale = getCustomizationLocale(customization); + const locale = getSpaceLocale(context); let language = fallback; // @ts-ignore @@ -33,3 +52,7 @@ export function getSpaceLanguage(customization: SiteCustomizationSettings): Tran ...language, }; } + +function checkIsValidLocale(locale: string): locale is TranslationLocale { + return locale in languages; +} diff --git a/packages/gitbook/src/intl/translations/index.ts b/packages/gitbook/src/intl/translations/index.ts index 06fc41268..be9500316 100644 --- a/packages/gitbook/src/intl/translations/index.ts +++ b/packages/gitbook/src/intl/translations/index.ts @@ -1,5 +1,3 @@ -import type { CustomizationLocale } from '@gitbook/api'; - import { de } from './de'; import { en } from './en'; import { es } from './es'; @@ -14,11 +12,7 @@ import { zh } from './zh'; export * from './types'; -export const languages: { - [key: string]: TranslationLanguage; -} & { - [locale in CustomizationLocale]: TranslationLanguage; -} = { +export const languages = { de, en, fr, @@ -29,4 +23,6 @@ export const languages: { no, 'pt-br': pt_br, ru, +} satisfies { + [key: string]: TranslationLanguage; };