mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 15:47:23 +02:00
feat: allow setting calendar for i18n date formatting (#6430)
* feat: allow setting calendar for i18n date formatting * fix TS * add test
This commit is contained in:
parent
3e110054d7
commit
7941a46be3
9 changed files with 54 additions and 12 deletions
|
@ -19,7 +19,11 @@ const DefaultI18N: I18n = {
|
||||||
currentLocale: 'en',
|
currentLocale: 'en',
|
||||||
locales: ['en'],
|
locales: ['en'],
|
||||||
defaultLocale: 'en',
|
defaultLocale: 'en',
|
||||||
localeConfigs: {},
|
localeConfigs: {
|
||||||
|
en: {
|
||||||
|
calendar: 'gregory',
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function getBlogContentPaths(siteDir: string): BlogContentPaths {
|
function getBlogContentPaths(siteDir: string): BlogContentPaths {
|
||||||
|
|
|
@ -41,7 +41,7 @@ function getI18n(locale: string): I18n {
|
||||||
currentLocale: locale,
|
currentLocale: locale,
|
||||||
locales: [locale],
|
locales: [locale],
|
||||||
defaultLocale: locale,
|
defaultLocale: locale,
|
||||||
localeConfigs: {},
|
localeConfigs: {[locale]: {calendar: 'gregory'}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -151,13 +151,18 @@ export function parseBlogFileName(
|
||||||
return {date: undefined, text, slug};
|
return {date: undefined, text, slug};
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatBlogPostDate(locale: string, date: Date): string {
|
function formatBlogPostDate(
|
||||||
|
locale: string,
|
||||||
|
date: Date,
|
||||||
|
calendar: string,
|
||||||
|
): string {
|
||||||
try {
|
try {
|
||||||
return new Intl.DateTimeFormat(locale, {
|
return new Intl.DateTimeFormat(locale, {
|
||||||
day: 'numeric',
|
day: 'numeric',
|
||||||
month: 'long',
|
month: 'long',
|
||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
timeZone: 'UTC',
|
timeZone: 'UTC',
|
||||||
|
calendar,
|
||||||
}).format(date);
|
}).format(date);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error`Can't format blog post date "${String(date)}"`;
|
logger.error`Can't format blog post date "${String(date)}"`;
|
||||||
|
@ -253,7 +258,11 @@ async function processBlogSourceFile(
|
||||||
}
|
}
|
||||||
|
|
||||||
const date = await getDate();
|
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 title = frontMatter.title ?? contentTitle ?? parsedBlogFileName.text;
|
||||||
const description = frontMatter.description ?? excerpt ?? '';
|
const description = frontMatter.description ?? excerpt ?? '';
|
||||||
|
|
|
@ -254,9 +254,9 @@ function doProcessDocMetadata({
|
||||||
lastUpdatedBy: lastUpdate.lastUpdatedBy,
|
lastUpdatedBy: lastUpdate.lastUpdatedBy,
|
||||||
lastUpdatedAt: lastUpdate.lastUpdatedAt,
|
lastUpdatedAt: lastUpdate.lastUpdatedAt,
|
||||||
formattedLastUpdatedAt: lastUpdate.lastUpdatedAt
|
formattedLastUpdatedAt: lastUpdate.lastUpdatedAt
|
||||||
? new Intl.DateTimeFormat(i18n.currentLocale).format(
|
? new Intl.DateTimeFormat(i18n.currentLocale, {
|
||||||
lastUpdate.lastUpdatedAt * 1000,
|
calendar: i18n.localeConfigs[i18n.currentLocale]!.calendar,
|
||||||
)
|
}).format(lastUpdate.lastUpdatedAt * 1000)
|
||||||
: undefined,
|
: undefined,
|
||||||
sidebarPosition,
|
sidebarPosition,
|
||||||
frontMatter,
|
frontMatter,
|
||||||
|
|
1
packages/docusaurus-types/src/index.d.ts
vendored
1
packages/docusaurus-types/src/index.d.ts
vendored
|
@ -45,6 +45,7 @@ export type I18nLocaleConfig = {
|
||||||
label: string;
|
label: string;
|
||||||
htmlLang: string;
|
htmlLang: string;
|
||||||
direction: string;
|
direction: string;
|
||||||
|
calendar: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type I18nConfig = {
|
export type I18nConfig = {
|
||||||
|
|
|
@ -32,48 +32,63 @@ describe('defaultLocaleConfig', () => {
|
||||||
label: 'Français',
|
label: 'Français',
|
||||||
direction: 'ltr',
|
direction: 'ltr',
|
||||||
htmlLang: 'fr',
|
htmlLang: 'fr',
|
||||||
|
calendar: 'gregory',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('fr-FR')).toEqual({
|
expect(getDefaultLocaleConfig('fr-FR')).toEqual({
|
||||||
label: 'Français (France)',
|
label: 'Français (France)',
|
||||||
direction: 'ltr',
|
direction: 'ltr',
|
||||||
htmlLang: 'fr-FR',
|
htmlLang: 'fr-FR',
|
||||||
|
calendar: 'gregory',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('en')).toEqual({
|
expect(getDefaultLocaleConfig('en')).toEqual({
|
||||||
label: 'English',
|
label: 'English',
|
||||||
direction: 'ltr',
|
direction: 'ltr',
|
||||||
htmlLang: 'en',
|
htmlLang: 'en',
|
||||||
|
calendar: 'gregory',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('en-US')).toEqual({
|
expect(getDefaultLocaleConfig('en-US')).toEqual({
|
||||||
label: 'American English',
|
label: 'American English',
|
||||||
direction: 'ltr',
|
direction: 'ltr',
|
||||||
htmlLang: 'en-US',
|
htmlLang: 'en-US',
|
||||||
|
calendar: 'gregory',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('zh')).toEqual({
|
expect(getDefaultLocaleConfig('zh')).toEqual({
|
||||||
label: '中文',
|
label: '中文',
|
||||||
direction: 'ltr',
|
direction: 'ltr',
|
||||||
htmlLang: 'zh',
|
htmlLang: 'zh',
|
||||||
|
calendar: 'gregory',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('zh-CN')).toEqual({
|
expect(getDefaultLocaleConfig('zh-CN')).toEqual({
|
||||||
label: '中文(中国)',
|
label: '中文(中国)',
|
||||||
direction: 'ltr',
|
direction: 'ltr',
|
||||||
htmlLang: 'zh-CN',
|
htmlLang: 'zh-CN',
|
||||||
|
calendar: 'gregory',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('en-US')).toEqual({
|
expect(getDefaultLocaleConfig('en-US')).toEqual({
|
||||||
label: 'American English',
|
label: 'American English',
|
||||||
direction: 'ltr',
|
direction: 'ltr',
|
||||||
htmlLang: 'en-US',
|
htmlLang: 'en-US',
|
||||||
|
calendar: 'gregory',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('fa')).toEqual({
|
expect(getDefaultLocaleConfig('fa')).toEqual({
|
||||||
// cSpell:ignore فارسی
|
// cSpell:ignore فارسی
|
||||||
label: 'فارسی',
|
label: 'فارسی',
|
||||||
direction: 'rtl',
|
direction: 'rtl',
|
||||||
htmlLang: 'fa',
|
htmlLang: 'fa',
|
||||||
|
calendar: 'gregory',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('fa-IR')).toEqual({
|
expect(getDefaultLocaleConfig('fa-IR')).toEqual({
|
||||||
// cSpell:ignore ایران فارسیا
|
// cSpell:ignore ایران فارسیا
|
||||||
label: 'فارسی (ایران)',
|
label: 'فارسی (ایران)',
|
||||||
direction: 'rtl',
|
direction: 'rtl',
|
||||||
htmlLang: 'fa-IR',
|
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'],
|
locales: ['en', 'fr', 'de'],
|
||||||
currentLocale: 'de',
|
currentLocale: 'de',
|
||||||
localeConfigs: {
|
localeConfigs: {
|
||||||
fr: {label: 'Français', direction: 'ltr', htmlLang: 'fr'},
|
fr: {
|
||||||
|
label: 'Français',
|
||||||
|
direction: 'ltr',
|
||||||
|
htmlLang: 'fr',
|
||||||
|
calendar: 'gregory',
|
||||||
|
},
|
||||||
en: getDefaultLocaleConfig('en'),
|
en: getDefaultLocaleConfig('en'),
|
||||||
de: getDefaultLocaleConfig('de'),
|
de: getDefaultLocaleConfig('de'),
|
||||||
},
|
},
|
||||||
|
|
|
@ -131,6 +131,7 @@ const LocaleConfigSchema = Joi.object({
|
||||||
label: Joi.string(),
|
label: Joi.string(),
|
||||||
htmlLang: Joi.string(),
|
htmlLang: Joi.string(),
|
||||||
direction: Joi.string().equal('ltr', 'rtl').default('ltr'),
|
direction: Joi.string().equal('ltr', 'rtl').default('ltr'),
|
||||||
|
calendar: Joi.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const I18N_CONFIG_SCHEMA = Joi.object<I18nConfig>({
|
const I18N_CONFIG_SCHEMA = Joi.object<I18nConfig>({
|
||||||
|
|
|
@ -24,6 +24,8 @@ export function getDefaultLocaleConfig(locale: string): I18nLocaleConfig {
|
||||||
label: getDefaultLocaleLabel(locale),
|
label: getDefaultLocaleLabel(locale),
|
||||||
direction: getLangDir(locale),
|
direction: getLangDir(locale),
|
||||||
htmlLang: locale,
|
htmlLang: locale,
|
||||||
|
// If the locale name includes -u-ca-xxx the calendar will be defined
|
||||||
|
calendar: new Intl.Locale(locale).calendar ?? 'gregory',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,8 @@ The i18n configuration object to [localize your site](../i18n/i18n-introduction.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
<!-- cSpell:ignore فارسی -->
|
||||||
|
|
||||||
```js title="docusaurus.config.js"
|
```js title="docusaurus.config.js"
|
||||||
module.exports = {
|
module.exports = {
|
||||||
i18n: {
|
i18n: {
|
||||||
|
@ -134,11 +136,13 @@ module.exports = {
|
||||||
label: 'English',
|
label: 'English',
|
||||||
direction: 'ltr',
|
direction: 'ltr',
|
||||||
htmlLang: 'en-US',
|
htmlLang: 'en-US',
|
||||||
|
calendar: 'gregory',
|
||||||
},
|
},
|
||||||
fr: {
|
fa: {
|
||||||
label: 'Français',
|
label: 'فارسی',
|
||||||
direction: 'ltr',
|
direction: 'rtl',
|
||||||
htmlLang: 'fr-FR',
|
htmlLang: 'fa-IR',
|
||||||
|
calendar: 'persian',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -148,6 +152,7 @@ module.exports = {
|
||||||
- `label`: the label to use for this locale
|
- `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.)
|
- `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 `<html lang="...">` and in `<link ... hreflang="...">`
|
- `htmlLang`: BCP 47 language tag to use in `<html lang="...">` and in `<link ... hreflang="...">`
|
||||||
|
- `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}
|
### `noIndex` {#noindex}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue