mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-23 19:06:31 +00:00
Use space.language as source of truth (#3606)
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@gitbook/colors": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix return type for `colorContrast`
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"gitbook": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Use space language as source of truth for UI locale
|
||||||
@@ -419,7 +419,10 @@ export function dpsContrast(a: RGBColor, b: RGBColor) {
|
|||||||
return contrast < 7.5 ? 0 : contrast;
|
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 bg = hexToRgbArray(background);
|
||||||
|
|
||||||
const best: { color?: RGBColor; contrast: number } = {
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ export default async function SiteDynamicLayout({
|
|||||||
const withTracking = shouldTrackEvents(await headers());
|
const withTracking = shouldTrackEvents(await headers());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomizationRootLayout forcedTheme={forcedTheme} customization={context.customization}>
|
<CustomizationRootLayout forcedTheme={forcedTheme} context={context}>
|
||||||
<SiteLayout
|
<SiteLayout
|
||||||
context={context}
|
context={context}
|
||||||
forcedTheme={forcedTheme}
|
forcedTheme={forcedTheme}
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ export default async function SiteStaticLayout({
|
|||||||
const withTracking = shouldTrackEvents();
|
const withTracking = shouldTrackEvents();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomizationRootLayout customization={context.customization}>
|
<CustomizationRootLayout context={context}>
|
||||||
<SiteLayout
|
<SiteLayout
|
||||||
context={context}
|
context={context}
|
||||||
withTracking={withTracking}
|
withTracking={withTracking}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ function DescriptionForPageContentToolCall(props: {
|
|||||||
}) {
|
}) {
|
||||||
const { toolCall, context } = props;
|
const { toolCall, context } = props;
|
||||||
|
|
||||||
const language = getSpaceLanguage(context.customization);
|
const language = getSpaceLanguage(context);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<p>
|
<p>
|
||||||
@@ -102,7 +102,7 @@ function DescriptionForMCPToolCall(props: {
|
|||||||
}) {
|
}) {
|
||||||
const { toolCall, context } = props;
|
const { toolCall, context } = props;
|
||||||
|
|
||||||
const language = getSpaceLanguage(context.customization);
|
const language = getSpaceLanguage(context);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<p>
|
<p>
|
||||||
@@ -130,7 +130,7 @@ async function DescriptionForSearchToolCall(props: {
|
|||||||
}) {
|
}) {
|
||||||
const { toolCall, context } = props;
|
const { toolCall, context } = props;
|
||||||
|
|
||||||
const language = getSpaceLanguage(context.customization);
|
const language = getSpaceLanguage(context);
|
||||||
|
|
||||||
// Resolve all hrefs for search results in parallel
|
// Resolve all hrefs for search results in parallel
|
||||||
const searchResultsWithHrefs = await Promise.all(
|
const searchResultsWithHrefs = await Promise.all(
|
||||||
@@ -241,7 +241,7 @@ function DescriptionForGetPagesToolCall(props: {
|
|||||||
}) {
|
}) {
|
||||||
const { toolCall, context } = props;
|
const { toolCall, context } = props;
|
||||||
|
|
||||||
const language = getSpaceLanguage(context.customization);
|
const language = getSpaceLanguage(context);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@@ -20,10 +20,7 @@ export async function InlineLink(props: InlineProps<DocumentInlineLink>) {
|
|||||||
: null;
|
: null;
|
||||||
const { contentContext } = context;
|
const { contentContext } = context;
|
||||||
|
|
||||||
const language =
|
const language = contentContext ? getSpaceLanguage(contentContext) : languages.en;
|
||||||
contentContext && 'customization' in contentContext
|
|
||||||
? getSpaceLanguage(contentContext.customization)
|
|
||||||
: languages.en;
|
|
||||||
|
|
||||||
if (!contentContext || !resolved) {
|
if (!contentContext || !resolved) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { Heading } from '../Heading';
|
|||||||
|
|
||||||
import './scalar.css';
|
import './scalar.css';
|
||||||
import './style.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 { GitBookAnyContext } from '@/lib/context';
|
||||||
import type {
|
import type {
|
||||||
AnyOpenAPIOperationsBlock,
|
AnyOpenAPIOperationsBlock,
|
||||||
@@ -30,10 +30,7 @@ export function getOpenAPIContext(args: {
|
|||||||
const { props, specUrl, context } = args;
|
const { props, specUrl, context } = args;
|
||||||
const { block } = props;
|
const { block } = props;
|
||||||
|
|
||||||
const customization = context && 'customization' in context ? context.customization : null;
|
const customizationLocale = context ? getSpaceLocale(context) : DEFAULT_LOCALE;
|
||||||
const customizationLocale = customization
|
|
||||||
? getCustomizationLocale(customization)
|
|
||||||
: DEFAULT_LOCALE;
|
|
||||||
const locale = checkIsValidLocale(customizationLocale) ? customizationLocale : DEFAULT_LOCALE;
|
const locale = checkIsValidLocale(customizationLocale) ? customizationLocale : DEFAULT_LOCALE;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export async function EmbeddableRootLayout({
|
|||||||
children,
|
children,
|
||||||
}: React.PropsWithChildren<EmbeddableRootLayoutProps>) {
|
}: React.PropsWithChildren<EmbeddableRootLayoutProps>) {
|
||||||
return (
|
return (
|
||||||
<CustomizationRootLayout customization={context.customization}>
|
<CustomizationRootLayout context={context}>
|
||||||
<SiteLayoutClientContexts
|
<SiteLayoutClientContexts
|
||||||
forcedTheme={context.customization.themes.default}
|
forcedTheme={context.customization.themes.default}
|
||||||
externalLinksTarget={context.customization.externalLinks.target}
|
externalLinksTarget={context.customization.externalLinks.target}
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ export function Header(props: {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<HeaderLinkMore
|
<HeaderLinkMore
|
||||||
label={t(getSpaceLanguage(customization), 'more')}
|
label={t(getSpaceLanguage(context), 'more')}
|
||||||
links={customization.header.links}
|
links={customization.header.links}
|
||||||
context={context}
|
context={context}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export async function PDFPage(props: {
|
|||||||
|
|
||||||
const customization =
|
const customization =
|
||||||
'customization' in baseContext ? baseContext.customization : defaultCustomization();
|
'customization' in baseContext ? baseContext.customization : defaultCustomization();
|
||||||
const language = getSpaceLanguage(customization);
|
const language = getSpaceLanguage(baseContext);
|
||||||
|
|
||||||
// Compute the pages to render
|
// Compute the pages to render
|
||||||
const { pages, total } = selectPages(baseContext.revision.pages, pdfParams);
|
const { pages, total } = selectPages(baseContext.revision.pages, pdfParams);
|
||||||
@@ -149,8 +149,7 @@ export async function PDFPage(props: {
|
|||||||
trademark={
|
trademark={
|
||||||
customization.trademark.enabled ? (
|
customization.trademark.enabled ? (
|
||||||
<TrademarkLink
|
<TrademarkLink
|
||||||
space={context.space}
|
context={context}
|
||||||
customization={customization}
|
|
||||||
placement={SiteInsightsTrademarkPlacement.Pdf}
|
placement={SiteInsightsTrademarkPlacement.Pdf}
|
||||||
/>
|
/>
|
||||||
) : null
|
) : null
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { CustomizationRootLayout } from '@/components/RootLayout';
|
import { CustomizationRootLayout } from '@/components/RootLayout';
|
||||||
import type { GitBookSiteContext, GitBookSpaceContext } from '@/lib/context';
|
import type { GitBookSiteContext, GitBookSpaceContext } from '@/lib/context';
|
||||||
import { defaultCustomization } from '@/lib/utils';
|
|
||||||
import { CustomizationThemeMode } from '@gitbook/api';
|
import { CustomizationThemeMode } from '@gitbook/api';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -13,12 +12,7 @@ export async function PDFRootLayout(props: {
|
|||||||
const { context, children } = props;
|
const { context, children } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomizationRootLayout
|
<CustomizationRootLayout context={context} forcedTheme={CustomizationThemeMode.Light}>
|
||||||
customization={
|
|
||||||
'customization' in context ? context.customization : defaultCustomization()
|
|
||||||
}
|
|
||||||
forcedTheme={CustomizationThemeMode.Light}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</CustomizationRootLayout>
|
</CustomizationRootLayout>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ export function PageAside(props: {
|
|||||||
|
|
||||||
function PageAsideHeader(props: { context: GitBookSiteContext }) {
|
function PageAsideHeader(props: { context: GitBookSiteContext }) {
|
||||||
const { context } = props;
|
const { context } = props;
|
||||||
const language = getSpaceLanguage(context.customization);
|
const language = getSpaceLanguage(context);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export function PageBody(props: {
|
|||||||
: false;
|
: false;
|
||||||
const pageWidthWide = page.layout.width === 'wide';
|
const pageWidthWide = page.layout.width === 'wide';
|
||||||
const siteWidthWide = pageWidthWide || contentFullWidth;
|
const siteWidthWide = pageWidthWide || contentFullWidth;
|
||||||
const language = getSpaceLanguage(customization);
|
const language = getSpaceLanguage(context);
|
||||||
const updatedAt = page.updatedAt ?? page.createdAt;
|
const updatedAt = page.updatedAt ?? page.createdAt;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ export async function PageFooterNavigation(props: {
|
|||||||
page: RevisionPageDocument;
|
page: RevisionPageDocument;
|
||||||
}) {
|
}) {
|
||||||
const { context, page } = props;
|
const { context, page } = props;
|
||||||
const { customization, revision, linker } = context;
|
const { revision, linker } = context;
|
||||||
const { previous, next } = resolvePrevNextPages(revision.pages, page);
|
const { previous, next } = resolvePrevNextPages(revision.pages, page);
|
||||||
const language = getSpaceLanguage(customization);
|
const language = getSpaceLanguage(context);
|
||||||
const previousHref = previous
|
const previousHref = previous
|
||||||
? linker.toPathForPage({ pages: revision.pages, page: previous })
|
? linker.toPathForPage({ pages: revision.pages, page: previous })
|
||||||
: '';
|
: '';
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ import { RootLayoutClientContexts } from './RootLayoutClientContexts';
|
|||||||
|
|
||||||
import '@gitbook/icons/style.css';
|
import '@gitbook/icons/style.css';
|
||||||
import './globals.css';
|
import './globals.css';
|
||||||
|
import type { GitBookAnyContext } from '@/lib/context';
|
||||||
import { GITBOOK_FONTS_URL, GITBOOK_ICONS_TOKEN, GITBOOK_ICONS_URL } from '@/lib/env';
|
import { GITBOOK_FONTS_URL, GITBOOK_ICONS_TOKEN, GITBOOK_ICONS_URL } from '@/lib/env';
|
||||||
|
import { defaultCustomization } from '@/lib/utils';
|
||||||
import { AnnouncementDismissedScript } from '../Announcement';
|
import { AnnouncementDismissedScript } from '../Announcement';
|
||||||
|
|
||||||
function preloadFont(fontData: FontData) {
|
function preloadFont(fontData: FontData) {
|
||||||
@@ -56,12 +58,14 @@ function preloadFont(fontData: FontData) {
|
|||||||
*/
|
*/
|
||||||
export async function CustomizationRootLayout(props: {
|
export async function CustomizationRootLayout(props: {
|
||||||
forcedTheme?: CustomizationThemeMode | null;
|
forcedTheme?: CustomizationThemeMode | null;
|
||||||
customization: SiteCustomizationSettings;
|
context: GitBookAnyContext;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
const { customization, forcedTheme, children } = props;
|
const { context, forcedTheme, children } = props;
|
||||||
|
const customization =
|
||||||
|
'customization' in context ? context.customization : defaultCustomization();
|
||||||
|
|
||||||
const language = getSpaceLanguage(customization);
|
const language = getSpaceLanguage(context);
|
||||||
const tintColor = getTintColor(customization);
|
const tintColor = getTintColor(customization);
|
||||||
const mixColor = getTintMixColor(customization.styling.primaryColor, tintColor);
|
const mixColor = getTintMixColor(customization.styling.primaryColor, tintColor);
|
||||||
const sidebarStyles = getSidebarStyles(customization);
|
const sidebarStyles = getSidebarStyles(customization);
|
||||||
@@ -141,7 +145,6 @@ export async function CustomizationRootLayout(props: {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
--header-link: ${hexToRgb(
|
--header-link: ${hexToRgb(
|
||||||
// @ts-expect-error
|
|
||||||
customization.header.linkColor?.light ??
|
customization.header.linkColor?.light ??
|
||||||
colorContrast(
|
colorContrast(
|
||||||
tintColor?.light ?? customization.styling.primaryColor.light
|
tintColor?.light ?? customization.styling.primaryColor.light
|
||||||
@@ -161,7 +164,6 @@ export async function CustomizationRootLayout(props: {
|
|||||||
|
|
||||||
--header-background: ${hexToRgb(customization.header.backgroundColor?.dark ?? tintColor?.dark ?? customization.styling.primaryColor.dark)};
|
--header-background: ${hexToRgb(customization.header.backgroundColor?.dark ?? tintColor?.dark ?? customization.styling.primaryColor.dark)};
|
||||||
--header-link: ${hexToRgb(
|
--header-link: ${hexToRgb(
|
||||||
// @ts-expect-error
|
|
||||||
customization.header.linkColor?.dark ??
|
customization.header.linkColor?.dark ??
|
||||||
colorContrast(
|
colorContrast(
|
||||||
tintColor?.dark ?? customization.styling.primaryColor.dark
|
tintColor?.dark ?? customization.styling.primaryColor.dark
|
||||||
@@ -337,7 +339,6 @@ function generateColorVariable(
|
|||||||
return Object.entries(shades)
|
return Object.entries(shades)
|
||||||
.map(([key, value]) => {
|
.map(([key, value]) => {
|
||||||
const rgbValue = hexToRgb(value); // Check the original hex value
|
const rgbValue = hexToRgb(value); // Check the original hex value
|
||||||
// @ts-expect-error
|
|
||||||
const contrastValue = withContrast ? hexToRgb(colorContrast(value)) : undefined; // Add contrast if needed
|
const contrastValue = withContrast ? hexToRgb(colorContrast(value)) : undefined; // Add contrast if needed
|
||||||
return `--${name}-${key}: ${rgbValue}; ${
|
return `--${name}-${key}: ${rgbValue}; ${
|
||||||
contrastValue ? `--contrast-${name}-${key}: ${contrastValue};` : ''
|
contrastValue ? `--contrast-${name}-${key}: ${contrastValue};` : ''
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export async function TableOfContents(props: {
|
|||||||
innerHeader?: React.ReactNode; // Displayed outside the scrollable TOC, directly above the page list
|
innerHeader?: React.ReactNode; // Displayed outside the scrollable TOC, directly above the page list
|
||||||
}) {
|
}) {
|
||||||
const { innerHeader, context, header } = props;
|
const { innerHeader, context, header } = props;
|
||||||
const { space, customization, revision } = context;
|
const { customization, revision } = context;
|
||||||
|
|
||||||
const pages = await encodeClientTableOfContents(context, revision.pages, revision.pages);
|
const pages = await encodeClientTableOfContents(context, revision.pages, revision.pages);
|
||||||
|
|
||||||
@@ -115,8 +115,7 @@ export async function TableOfContents(props: {
|
|||||||
/>
|
/>
|
||||||
{customization.trademark.enabled ? (
|
{customization.trademark.enabled ? (
|
||||||
<Trademark
|
<Trademark
|
||||||
space={space}
|
context={context}
|
||||||
customization={customization}
|
|
||||||
placement={SiteInsightsTrademarkPlacement.Sidebar}
|
placement={SiteInsightsTrademarkPlacement.Sidebar}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -1,21 +1,17 @@
|
|||||||
import type {
|
import type { SiteInsightsTrademarkPlacement } from '@gitbook/api';
|
||||||
SiteCustomizationSettings,
|
|
||||||
SiteInsightsTrademarkPlacement,
|
|
||||||
Space,
|
|
||||||
} from '@gitbook/api';
|
|
||||||
import { Icon } from '@gitbook/icons';
|
import { Icon } from '@gitbook/icons';
|
||||||
|
|
||||||
import { getSpaceLanguage, t } from '@/intl/server';
|
import { getSpaceLanguage, t } from '@/intl/server';
|
||||||
import { tcls } from '@/lib/tailwind';
|
import { tcls } from '@/lib/tailwind';
|
||||||
|
|
||||||
|
import type { GitBookSpaceContext } from '@/lib/context';
|
||||||
import { Link } from '../primitives';
|
import { Link } from '../primitives';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trademark link to the GitBook.
|
* Trademark link to the GitBook.
|
||||||
*/
|
*/
|
||||||
export function Trademark(props: {
|
export function Trademark(props: {
|
||||||
space: Space;
|
context: GitBookSpaceContext;
|
||||||
customization: SiteCustomizationSettings;
|
|
||||||
placement: SiteInsightsTrademarkPlacement;
|
placement: SiteInsightsTrademarkPlacement;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
@@ -71,12 +67,12 @@ export function Trademark(props: {
|
|||||||
* Trademark link to the GitBook.
|
* Trademark link to the GitBook.
|
||||||
*/
|
*/
|
||||||
export function TrademarkLink(props: {
|
export function TrademarkLink(props: {
|
||||||
space: Space;
|
context: GitBookSpaceContext;
|
||||||
customization: SiteCustomizationSettings;
|
|
||||||
placement: SiteInsightsTrademarkPlacement;
|
placement: SiteInsightsTrademarkPlacement;
|
||||||
}) {
|
}) {
|
||||||
const { space, customization, placement } = props;
|
const { context, placement } = props;
|
||||||
const language = getSpaceLanguage(customization);
|
const { space } = context;
|
||||||
|
const language = getSpaceLanguage(context);
|
||||||
|
|
||||||
const url = new URL('https://www.gitbook.com');
|
const url = new URL('https://www.gitbook.com');
|
||||||
url.searchParams.set('utm_source', 'content');
|
url.searchParams.set('utm_source', 'content');
|
||||||
|
|||||||
@@ -1,25 +1,44 @@
|
|||||||
import type { SiteCustomizationSettings } from '@gitbook/api';
|
import type { GitBookAnyContext } from '@/lib/context';
|
||||||
|
|
||||||
import { type TranslationLanguage, languages } from './translations';
|
import { type TranslationLanguage, languages } from './translations';
|
||||||
|
|
||||||
export * from './translate';
|
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 {
|
export function getSpaceLocale(context: GitBookAnyContext): TranslationLocale {
|
||||||
return customization.internationalization.locale;
|
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.
|
* 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 fallback = languages[DEFAULT_LOCALE];
|
||||||
|
|
||||||
const locale = getCustomizationLocale(customization);
|
const locale = getSpaceLocale(context);
|
||||||
|
|
||||||
let language = fallback;
|
let language = fallback;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@@ -33,3 +52,7 @@ export function getSpaceLanguage(customization: SiteCustomizationSettings): Tran
|
|||||||
...language,
|
...language,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkIsValidLocale(locale: string): locale is TranslationLocale {
|
||||||
|
return locale in languages;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import type { CustomizationLocale } from '@gitbook/api';
|
|
||||||
|
|
||||||
import { de } from './de';
|
import { de } from './de';
|
||||||
import { en } from './en';
|
import { en } from './en';
|
||||||
import { es } from './es';
|
import { es } from './es';
|
||||||
@@ -14,11 +12,7 @@ import { zh } from './zh';
|
|||||||
|
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
|
||||||
export const languages: {
|
export const languages = {
|
||||||
[key: string]: TranslationLanguage;
|
|
||||||
} & {
|
|
||||||
[locale in CustomizationLocale]: TranslationLanguage;
|
|
||||||
} = {
|
|
||||||
de,
|
de,
|
||||||
en,
|
en,
|
||||||
fr,
|
fr,
|
||||||
@@ -29,4 +23,6 @@ export const languages: {
|
|||||||
no,
|
no,
|
||||||
'pt-br': pt_br,
|
'pt-br': pt_br,
|
||||||
ru,
|
ru,
|
||||||
|
} satisfies {
|
||||||
|
[key: string]: TranslationLanguage;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user