From 779242c688c85ec9ff9b373d666f81b2df4f22eb Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Fri, 21 Jan 2022 22:17:13 +0800 Subject: [PATCH 1/3] feat: allow setting calendar for i18n date formatting --- .../src/index.d.ts | 1 + .../src/__tests__/feed.test.ts | 6 +++++- .../src/__tests__/index.test.ts | 2 +- .../src/blogUtils.ts | 13 +++++++++++-- .../docusaurus-plugin-content-docs/src/docs.ts | 6 +++--- packages/docusaurus-types/src/index.d.ts | 1 + .../docusaurus/src/server/__tests__/i18n.test.ts | 16 +++++++++++++++- .../docusaurus/src/server/configValidation.ts | 1 + packages/docusaurus/src/server/i18n.ts | 2 ++ website/docs/api/docusaurus.config.js.md | 11 +++++++---- 10 files changed, 47 insertions(+), 12 deletions(-) diff --git a/packages/docusaurus-module-type-aliases/src/index.d.ts b/packages/docusaurus-module-type-aliases/src/index.d.ts index 72228dd6f009..88fc097734bb 100644 --- a/packages/docusaurus-module-type-aliases/src/index.d.ts +++ b/packages/docusaurus-module-type-aliases/src/index.d.ts @@ -70,6 +70,7 @@ declare module '@generated/i18n' { label: string; direction: string; htmlLang: string; + calendar: string; } >; }; 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 d6d5d1f2d33a..b39c964cc180 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts @@ -18,7 +18,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 c6f1a8ca38da..aab15deb65c2 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts @@ -40,7 +40,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 ddda9dc01684..766f9f2d8c73 100644 --- a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts +++ b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts @@ -89,13 +89,18 @@ export function parseBlogFileName( } } -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 (e) { throw new Error(`Can't format blog post date "${date}"`); @@ -184,7 +189,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 e857436fcecf..0bd440cc1523 100644 --- a/packages/docusaurus-plugin-content-docs/src/docs.ts +++ b/packages/docusaurus-plugin-content-docs/src/docs.ts @@ -255,9 +255,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 d2fe18dab056..58907837d124 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -122,6 +122,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 399bd928bf83..a3b1a94c38a0 100644 --- a/packages/docusaurus/src/server/__tests__/i18n.test.ts +++ b/packages/docusaurus/src/server/__tests__/i18n.test.ts @@ -41,46 +41,55 @@ describe('defaultLocaleConfig', () => { label: canComputeLabel ? 'Français' : 'fr', direction: 'ltr', htmlLang: 'fr', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('fr-FR')).toEqual({ label: canComputeLabel ? 'Français (France)' : 'fr-FR', direction: 'ltr', htmlLang: 'fr-FR', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('en')).toEqual({ label: canComputeLabel ? 'English' : 'en', direction: 'ltr', htmlLang: 'en', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('en-US')).toEqual({ label: canComputeLabel ? 'American English' : 'en-US', direction: 'ltr', htmlLang: 'en-US', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('zh')).toEqual({ label: canComputeLabel ? '中文' : 'zh', direction: 'ltr', htmlLang: 'zh', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('zh-CN')).toEqual({ label: canComputeLabel ? '中文(中国)' : 'zh-CN', direction: 'ltr', htmlLang: 'zh-CN', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('en-US')).toEqual({ label: canComputeLabel ? 'American English' : 'en-US', direction: 'ltr', htmlLang: 'en-US', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('fa')).toEqual({ label: canComputeLabel ? 'فارسی' : 'fa', direction: 'rtl', htmlLang: 'fa', + calendar: 'gregory', }); expect(getDefaultLocaleConfig('fa-IR')).toEqual({ label: canComputeLabel ? 'فارسی (ایران)' : 'fa-IR', direction: 'rtl', htmlLang: 'fa-IR', + calendar: 'gregory', }); }); }); @@ -165,7 +174,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 420315ff0da9..1e013722b744 100644 --- a/packages/docusaurus/src/server/configValidation.ts +++ b/packages/docusaurus/src/server/configValidation.ts @@ -98,6 +98,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 6a847d6e9b8a..1965157b2ee4 100644 --- a/packages/docusaurus/src/server/i18n.ts +++ b/packages/docusaurus/src/server/i18n.ts @@ -25,6 +25,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 ab50dc53956c..23a65aae2410 100644 --- a/website/docs/api/docusaurus.config.js.md +++ b/website/docs/api/docusaurus.config.js.md @@ -134,11 +134,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 +150,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: `YYYY/MM/DD` and `DD/MM/YYYY` are both `gregory`. ### `noIndex` {#noindex} From 12610d7328fe621810704486c973012d2f252660 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Fri, 8 Apr 2022 16:29:57 +0800 Subject: [PATCH 2/3] fix TS --- packages/docusaurus-plugin-content-blog/src/blogUtils.ts | 2 +- packages/docusaurus-plugin-content-docs/src/docs.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts index 7396295c29e1..6b839cee9d42 100644 --- a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts +++ b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts @@ -261,7 +261,7 @@ async function processBlogSourceFile( const formattedDate = formatBlogPostDate( i18n.currentLocale, date, - i18n.localeConfigs[i18n.currentLocale].calendar, + i18n.localeConfigs[i18n.currentLocale]!.calendar, ); const title = frontMatter.title ?? contentTitle ?? parsedBlogFileName.text; diff --git a/packages/docusaurus-plugin-content-docs/src/docs.ts b/packages/docusaurus-plugin-content-docs/src/docs.ts index 6e3e3ee93a8b..c5057800f3c9 100644 --- a/packages/docusaurus-plugin-content-docs/src/docs.ts +++ b/packages/docusaurus-plugin-content-docs/src/docs.ts @@ -255,7 +255,7 @@ function doProcessDocMetadata({ lastUpdatedAt: lastUpdate.lastUpdatedAt, formattedLastUpdatedAt: lastUpdate.lastUpdatedAt ? new Intl.DateTimeFormat(i18n.currentLocale, { - calendar: i18n.localeConfigs[i18n.currentLocale].calendar, + calendar: i18n.localeConfigs[i18n.currentLocale]!.calendar, }).format(lastUpdate.lastUpdatedAt * 1000) : undefined, sidebarPosition, From 0084e719d183cd4597619c780898c6f1827ba70a Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Fri, 8 Apr 2022 21:58:09 +0800 Subject: [PATCH 3/3] add test --- packages/docusaurus/src/server/__tests__/i18n.test.ts | 6 ++++++ website/docs/api/docusaurus.config.js.md | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus/src/server/__tests__/i18n.test.ts b/packages/docusaurus/src/server/__tests__/i18n.test.ts index c6a0d6f0b960..5142d0972fbb 100644 --- a/packages/docusaurus/src/server/__tests__/i18n.test.ts +++ b/packages/docusaurus/src/server/__tests__/i18n.test.ts @@ -84,6 +84,12 @@ describe('defaultLocaleConfig', () => { 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', + }); }); }); diff --git a/website/docs/api/docusaurus.config.js.md b/website/docs/api/docusaurus.config.js.md index 74873e3083f6..932dd352ea4f 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: { @@ -150,7 +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: `YYYY/MM/DD` and `DD/MM/YYYY` are both `gregory`. +- `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}