blob: dd7d7f5d7e4b60454a7f496e964e02b721a05822 [file]
import useGlobalData from '@docusaurus/useGlobalData';
import {useLocation} from '@docusaurus/router';
import i18n from '@generated/i18n';
import {hasTranslatedPage, translatedPagePaths, usesDefaultLocalePages} from './localization';
import {normalizePathname} from './locale';
import {useContentRouteData} from './contentRoute';
export type TranslationState = {
status: string;
contentLocale: string;
indexable: boolean;
useTarget: boolean;
reviewStatus: 'machine' | 'human' | 'manual' | 'unverified';
translatedAt: string | null;
englishPermalink: string;
sourcePermalink: string;
englishPath: string;
sourcePath: string;
targetPath: string;
};
export function docTranslation(metadata: unknown): TranslationState | undefined {
return (metadata as {translation?: TranslationState}).translation;
}
type StatusData = {alternates: Record<string, Record<string, string>>; prefixes: string[]; locales?: string[]; pageRoutes?: string[]};
export function useTranslationRoutes() {
const content = useContentRouteData();
const data = useGlobalData()['doris-translation-status']?.default as StatusData | undefined;
const {pathname} = useLocation();
const route = pathname.replace(/\/$/, '') + '/';
const pagePath = normalizePathname(pathname, i18n.locales).replace(/\/+$/, '');
const pageLocales = Object.keys(translatedPagePaths).filter(locale => hasTranslatedPage(pagePath, locale));
const ordinaryPage = data?.pageRoutes?.includes(route) ?? false;
const pageFallback = ordinaryPage && usesDefaultLocalePages() && !hasTranslatedPage(pathname);
if (content?.renderIntegrated) return {
group: contentRouteGroups(content).indexableTranslations,
navigationGroup: content.navigationRoutes,
translatedLocales: data?.locales ?? [], managed: true,
pageFallback: content.kind === 'page' && content.fallback,
};
if (pageLocales.length) {
return {
group: Object.fromEntries([i18n.defaultLocale, ...pageLocales].map(locale => [locale,
`${locale === i18n.defaultLocale ? '' : `/${locale}`}${pagePath}/`])),
translatedLocales: data?.locales ?? [],
managed: true,
pageFallback,
};
}
return {group: data?.alternates[route],
// Locales with translation state. A page outside a translated route
// group must not offer them as an alternate, because the target page
// would only repeat the default locale's content.
translatedLocales: data?.locales ?? [],
managed: ordinaryPage || !!data?.prefixes.some(prefix => route === prefix || route.startsWith(prefix.replace(/\/$/, '') + '/')),
pageFallback};
}
// T01 consumers accept one page's routing payload. The build-only registry
// (source/target digests, state and reports) must not be imported by the browser.
export type ContentRouteData = {
aggregate?: boolean;
schemaVersion: 1;
renderIntegrated: boolean;
contentId: string;
kind: 'docs' | 'page' | 'blog' | 'utility';
siteLocale: string;
contentLocale: string;
fallback: boolean;
indexable: boolean;
navigationRoutes: Record<string, string>;
availableTranslations: string[];
};
export function contentRouteGroups(page: ContentRouteData) {
return {
navigationRoutes: page.navigationRoutes,
indexableTranslations: Object.fromEntries(page.availableTranslations
.map(locale => [locale, page.navigationRoutes[locale]])),
};
}