diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts index facf967523..f7d31a7dbb 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts @@ -19,7 +19,11 @@ const DefaultI18N: I18n = { currentLocale: 'en', locales: ['en'], defaultLocale: 'en', - localeConfigs: {}, + localeConfigs: { + en: { + calendar: 'gregory', + }, + }, }; function getBlogContentPaths(siteDir: string): BlogContentPaths { diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts index 2a19736683..79ec1bb2b0 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts @@ -41,7 +41,7 @@ function getI18n(locale: string): I18n { currentLocale: locale, locales: [locale], defaultLocale: locale, - localeConfigs: {}, + localeConfigs: {[locale]: {calendar: 'gregory'}}, }; } diff --git a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts index 8138d1ab8b..6b839cee9d 100644 --- a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts +++ b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts @@ -151,13 +151,18 @@ export function parseBlogFileName( return {date: undefined, text, slug}; } -function formatBlogPostDate(locale: string, date: Date): string { +function formatBlogPostDate( + locale: string, + date: Date, + calendar: string, +): string { try { return new Intl.DateTimeFormat(locale, { day: 'numeric', month: 'long', year: 'numeric', timeZone: 'UTC', + calendar, }).format(date); } catch (err) { logger.error`Can't format blog post date "${String(date)}"`; @@ -253,7 +258,11 @@ async function processBlogSourceFile( } const date = await getDate(); - const formattedDate = formatBlogPostDate(i18n.currentLocale, date); + const formattedDate = formatBlogPostDate( + i18n.currentLocale, + date, + i18n.localeConfigs[i18n.currentLocale]!.calendar, + ); const title = frontMatter.title ?? contentTitle ?? parsedBlogFileName.text; const description = frontMatter.description ?? excerpt ?? ''; diff --git a/packages/docusaurus-plugin-content-docs/src/docs.ts b/packages/docusaurus-plugin-content-docs/src/docs.ts index ee247ec0a9..c5057800f3 100644 --- a/packages/docusaurus-plugin-content-docs/src/docs.ts +++ b/packages/docusaurus-plugin-content-docs/src/docs.ts @@ -254,9 +254,9 @@ function doProcessDocMetadata({ lastUpdatedBy: lastUpdate.lastUpdatedBy, lastUpdatedAt: lastUpdate.lastUpdatedAt, formattedLastUpdatedAt: lastUpdate.lastUpdatedAt - ? new Intl.DateTimeFormat(i18n.currentLocale).format( - lastUpdate.lastUpdatedAt * 1000, - ) + ? new Intl.DateTimeFormat(i18n.currentLocale, { + calendar: i18n.localeConfigs[i18n.currentLocale]!.calendar, + }).format(lastUpdate.lastUpdatedAt * 1000) : undefined, sidebarPosition, frontMatter, diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index 9c19ac7edc..348a3ded43 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -45,6 +45,7 @@ export type I18nLocaleConfig = { label: string; htmlLang: string; direction: string; + calendar: string; }; export type I18nConfig = { diff --git a/packages/docusaurus/src/server/__tests__/i18n.test.ts b/packages/docusaurus/src/server/__tests__/i18n.test.ts index 258adfbe7c..5142d0972f 100644 --- a/packages/docusaurus/src/server/__tests__/i18n.test.ts +++ b/packages/docusaurus/src/server/__tests__/i18n.test.ts @@ -32,48 +32,63 @@ describe('defaultLocaleConfig', () => { label: 'Français', direction: 'ltr', htmlLang: 'fr', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('fr-FR')).toEqual({ label: 'Français (France)', direction: 'ltr', htmlLang: 'fr-FR', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('en')).toEqual({ label: 'English', direction: 'ltr', htmlLang: 'en', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('en-US')).toEqual({ label: 'American English', direction: 'ltr', htmlLang: 'en-US', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('zh')).toEqual({ label: '中文', direction: 'ltr', htmlLang: 'zh', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('zh-CN')).toEqual({ label: '中文(中国)', direction: 'ltr', htmlLang: 'zh-CN', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('en-US')).toEqual({ label: 'American English', direction: 'ltr', htmlLang: 'en-US', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('fa')).toEqual({ // cSpell:ignore فارسی label: 'فارسی', direction: 'rtl', htmlLang: 'fa', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('fa-IR')).toEqual({ // cSpell:ignore ایران فارسیا label: 'فارسی (ایران)', direction: 'rtl', htmlLang: 'fa-IR', + calendar: 'gregory', + }); + expect(getDefaultLocaleConfig('en-US-u-ca-buddhist')).toEqual({ + label: 'American English', + direction: 'ltr', + htmlLang: 'en-US-u-ca-buddhist', + calendar: 'buddhist', }); }); }); @@ -144,7 +159,12 @@ describe('loadI18n', () => { locales: ['en', 'fr', 'de'], currentLocale: 'de', localeConfigs: { - fr: {label: 'Français', direction: 'ltr', htmlLang: 'fr'}, + fr: { + label: 'Français', + direction: 'ltr', + htmlLang: 'fr', + calendar: 'gregory', + }, en: getDefaultLocaleConfig('en'), de: getDefaultLocaleConfig('de'), }, diff --git a/packages/docusaurus/src/server/configValidation.ts b/packages/docusaurus/src/server/configValidation.ts index 74f3836b0e..007c3d1d5b 100644 --- a/packages/docusaurus/src/server/configValidation.ts +++ b/packages/docusaurus/src/server/configValidation.ts @@ -131,6 +131,7 @@ const LocaleConfigSchema = Joi.object({ label: Joi.string(), htmlLang: Joi.string(), direction: Joi.string().equal('ltr', 'rtl').default('ltr'), + calendar: Joi.string(), }); const I18N_CONFIG_SCHEMA = Joi.object({ diff --git a/packages/docusaurus/src/server/i18n.ts b/packages/docusaurus/src/server/i18n.ts index b2d5dfe570..57f639c140 100644 --- a/packages/docusaurus/src/server/i18n.ts +++ b/packages/docusaurus/src/server/i18n.ts @@ -24,6 +24,8 @@ export function getDefaultLocaleConfig(locale: string): I18nLocaleConfig { label: getDefaultLocaleLabel(locale), direction: getLangDir(locale), htmlLang: locale, + // If the locale name includes -u-ca-xxx the calendar will be defined + calendar: new Intl.Locale(locale).calendar ?? 'gregory', }; } diff --git a/website/docs/api/docusaurus.config.js.md b/website/docs/api/docusaurus.config.js.md index 5a52885277..932dd352ea 100644 --- a/website/docs/api/docusaurus.config.js.md +++ b/website/docs/api/docusaurus.config.js.md @@ -124,6 +124,8 @@ The i18n configuration object to [localize your site](../i18n/i18n-introduction. Example: + + ```js title="docusaurus.config.js" module.exports = { i18n: { @@ -134,11 +136,13 @@ module.exports = { label: 'English', direction: 'ltr', htmlLang: 'en-US', + calendar: 'gregory', }, - fr: { - label: 'Français', - direction: 'ltr', - htmlLang: 'fr-FR', + fa: { + label: 'فارسی', + direction: 'rtl', + htmlLang: 'fa-IR', + calendar: 'persian', }, }, }, @@ -148,6 +152,7 @@ module.exports = { - `label`: the label to use for this locale - `direction`: `ltr` (default) or `rtl` (for [right-to-left languages](https://developer.mozilla.org/en-US/docs/Glossary/rtl) like Arabic, Hebrew, etc.) - `htmlLang`: BCP 47 language tag to use in `` and in `` +- `calendar`: the [calendar](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/calendar) used to calculate the date era. Note that it doesn't control the actual string displayed: `MM/DD/YYYY` and `DD/MM/YYYY` are both `gregory`. To choose the format (`DD/MM/YYYY` or `MM/DD/YYYY`), set your locale name to `en-GB` or `en-US` (`en` means `en-US`). ### `noIndex` {#noindex}