mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 18:27:56 +02:00
124 lines
3.5 KiB
TypeScript
124 lines
3.5 KiB
TypeScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
import logger from '@docusaurus/logger';
|
|
import {getLangDir} from 'rtl-detect';
|
|
import type {I18n, DocusaurusConfig, I18nLocaleConfig} from '@docusaurus/types';
|
|
import type {LoadContextParams} from './site';
|
|
|
|
function inferLanguageDisplayName(locale: string) {
|
|
const tryLocale = (l: string) => {
|
|
try {
|
|
return new Intl.DisplayNames(l, {
|
|
type: 'language',
|
|
fallback: 'code',
|
|
}).of(l)!;
|
|
} catch (e) {
|
|
// This is to compensate "of()" that is a bit strict
|
|
// Looks like starting Node 22, this locale throws: "en-US-u-ca-buddhist"
|
|
// RangeError: invalid_argument
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const parts = locale.split('-');
|
|
|
|
// This is a best effort, we try various locale forms that could give a result
|
|
return (
|
|
tryLocale(locale) ??
|
|
tryLocale(`${parts[0]}-${parts[1]}`) ??
|
|
tryLocale(parts[0]!)
|
|
);
|
|
}
|
|
|
|
function getDefaultLocaleLabel(locale: string) {
|
|
const languageName = inferLanguageDisplayName(locale);
|
|
if (!languageName) {
|
|
return locale;
|
|
}
|
|
return (
|
|
languageName.charAt(0).toLocaleUpperCase(locale) + languageName.substring(1)
|
|
);
|
|
}
|
|
|
|
function getDefaultCalendar(localeStr: string) {
|
|
const locale = new Intl.Locale(localeStr);
|
|
|
|
// If the locale name includes -u-ca-xxx the calendar will be defined
|
|
if (locale.calendar) {
|
|
return locale.calendar;
|
|
}
|
|
|
|
// Not well-supported but server code can infer a calendar from the locale
|
|
// See https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getCalendars
|
|
// See https://caniuse.com/mdn-javascript_builtins_intl_locale_getcalendars
|
|
const calendars =
|
|
// @ts-expect-error: new std method (Bun/JSC/WebKit)
|
|
locale.getCalendars?.() ??
|
|
// @ts-expect-error: non-std attribute (V8/Chromium/Node)
|
|
locale.calendars;
|
|
|
|
if (calendars instanceof Array && calendars[0]) {
|
|
return calendars[0];
|
|
}
|
|
|
|
return 'gregory';
|
|
}
|
|
|
|
export function getDefaultLocaleConfig(locale: string): I18nLocaleConfig {
|
|
try {
|
|
return {
|
|
label: getDefaultLocaleLabel(locale),
|
|
direction: getLangDir(locale),
|
|
htmlLang: locale,
|
|
calendar: getDefaultCalendar(locale),
|
|
path: locale,
|
|
};
|
|
} catch (e) {
|
|
throw new Error(
|
|
`Docusaurus couldn't get default locale config for ${locale}`,
|
|
{cause: e},
|
|
);
|
|
}
|
|
}
|
|
|
|
export async function loadI18n(
|
|
config: DocusaurusConfig,
|
|
options?: Pick<LoadContextParams, 'locale'>,
|
|
): Promise<I18n> {
|
|
const {i18n: i18nConfig} = config;
|
|
|
|
const currentLocale = options?.locale ?? i18nConfig.defaultLocale;
|
|
|
|
if (!i18nConfig.locales.includes(currentLocale)) {
|
|
logger.warn`The locale name=${currentLocale} was not found in your site configuration: Available locales are: ${i18nConfig.locales}
|
|
Note: Docusaurus only support running one locale at a time.`;
|
|
}
|
|
|
|
const locales = i18nConfig.locales.includes(currentLocale)
|
|
? i18nConfig.locales
|
|
: (i18nConfig.locales.concat(currentLocale) as [string, ...string[]]);
|
|
|
|
function getLocaleConfig(locale: string): I18nLocaleConfig {
|
|
return {
|
|
...getDefaultLocaleConfig(locale),
|
|
...i18nConfig.localeConfigs[locale],
|
|
};
|
|
}
|
|
|
|
const localeConfigs = Object.fromEntries(
|
|
locales.map((locale) => [locale, getLocaleConfig(locale)]),
|
|
);
|
|
|
|
return {
|
|
defaultLocale: i18nConfig.defaultLocale,
|
|
locales,
|
|
path: i18nConfig.path,
|
|
currentLocale,
|
|
localeConfigs,
|
|
};
|
|
}
|