mirror of
https://github.com/facebook/docusaurus.git
synced 2025-07-26 04:57:50 +02:00
feat(core, theme-classic): allow overriding htmlLang (#6371)
This commit is contained in:
parent
732ecd18e8
commit
6f892e20b0
6 changed files with 25 additions and 10 deletions
|
@ -64,7 +64,14 @@ declare module '@generated/i18n' {
|
||||||
defaultLocale: string;
|
defaultLocale: string;
|
||||||
locales: [string, ...string[]];
|
locales: [string, ...string[]];
|
||||||
currentLocale: string;
|
currentLocale: string;
|
||||||
localeConfigs: Record<string, {label: string; direction: string}>;
|
localeConfigs: Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
label: string;
|
||||||
|
direction: string;
|
||||||
|
htmlLang: string;
|
||||||
|
}
|
||||||
|
>;
|
||||||
};
|
};
|
||||||
export = i18n;
|
export = i18n;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import {useLocation} from '@docusaurus/router';
|
||||||
// See https://github.com/facebook/docusaurus/issues/3317
|
// See https://github.com/facebook/docusaurus/issues/3317
|
||||||
function AlternateLangHeaders(): JSX.Element {
|
function AlternateLangHeaders(): JSX.Element {
|
||||||
const {
|
const {
|
||||||
i18n: {defaultLocale, locales},
|
i18n: {defaultLocale, localeConfigs},
|
||||||
} = useDocusaurusContext();
|
} = useDocusaurusContext();
|
||||||
const alternatePageUtils = useAlternatePageUtils();
|
const alternatePageUtils = useAlternatePageUtils();
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ function AlternateLangHeaders(): JSX.Element {
|
||||||
// See https://www.searchviu.com/en/multiple-hreflang-tags-one-url/
|
// See https://www.searchviu.com/en/multiple-hreflang-tags-one-url/
|
||||||
return (
|
return (
|
||||||
<Head>
|
<Head>
|
||||||
{locales.map((locale) => (
|
{Object.entries(localeConfigs).map(([locale, {htmlLang}]) => (
|
||||||
<link
|
<link
|
||||||
key={locale}
|
key={locale}
|
||||||
rel="alternate"
|
rel="alternate"
|
||||||
|
@ -41,7 +41,7 @@ function AlternateLangHeaders(): JSX.Element {
|
||||||
locale,
|
locale,
|
||||||
fullyQualified: true,
|
fullyQualified: true,
|
||||||
})}
|
})}
|
||||||
hrefLang={locale}
|
hrefLang={htmlLang}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<link
|
<link
|
||||||
|
@ -91,11 +91,7 @@ export default function LayoutHead(props: Props): JSX.Element {
|
||||||
const {title, description, image, keywords, searchMetadata} = props;
|
const {title, description, image, keywords, searchMetadata} = props;
|
||||||
const faviconUrl = useBaseUrl(favicon);
|
const faviconUrl = useBaseUrl(favicon);
|
||||||
const pageTitle = useTitleFormatter(title);
|
const pageTitle = useTitleFormatter(title);
|
||||||
|
const {htmlLang, direction: htmlDir} = localeConfigs[currentLocale];
|
||||||
// See https://github.com/facebook/docusaurus/issues/3317#issuecomment-754661855
|
|
||||||
// const htmlLang = currentLocale.split('-')[0];
|
|
||||||
const htmlLang = currentLocale; // should we allow the user to override htmlLang with localeConfig?
|
|
||||||
const htmlDir = localeConfigs[currentLocale].direction;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
1
packages/docusaurus-types/src/index.d.ts
vendored
1
packages/docusaurus-types/src/index.d.ts
vendored
|
@ -120,6 +120,7 @@ export type TranslationFiles = TranslationFile[];
|
||||||
|
|
||||||
export type I18nLocaleConfig = {
|
export type I18nLocaleConfig = {
|
||||||
label: string;
|
label: string;
|
||||||
|
htmlLang: string;
|
||||||
direction: string;
|
direction: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,38 +40,47 @@ describe('defaultLocaleConfig', () => {
|
||||||
expect(getDefaultLocaleConfig('fr')).toEqual({
|
expect(getDefaultLocaleConfig('fr')).toEqual({
|
||||||
label: canComputeLabel ? 'Français' : 'fr',
|
label: canComputeLabel ? 'Français' : 'fr',
|
||||||
direction: 'ltr',
|
direction: 'ltr',
|
||||||
|
htmlLang: 'fr',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('fr-FR')).toEqual({
|
expect(getDefaultLocaleConfig('fr-FR')).toEqual({
|
||||||
label: canComputeLabel ? 'Français (France)' : 'fr-FR',
|
label: canComputeLabel ? 'Français (France)' : 'fr-FR',
|
||||||
direction: 'ltr',
|
direction: 'ltr',
|
||||||
|
htmlLang: 'fr-FR',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('en')).toEqual({
|
expect(getDefaultLocaleConfig('en')).toEqual({
|
||||||
label: canComputeLabel ? 'English' : 'en',
|
label: canComputeLabel ? 'English' : 'en',
|
||||||
direction: 'ltr',
|
direction: 'ltr',
|
||||||
|
htmlLang: 'en',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('en-US')).toEqual({
|
expect(getDefaultLocaleConfig('en-US')).toEqual({
|
||||||
label: canComputeLabel ? 'American English' : 'en-US',
|
label: canComputeLabel ? 'American English' : 'en-US',
|
||||||
direction: 'ltr',
|
direction: 'ltr',
|
||||||
|
htmlLang: 'en-US',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('zh')).toEqual({
|
expect(getDefaultLocaleConfig('zh')).toEqual({
|
||||||
label: canComputeLabel ? '中文' : 'zh',
|
label: canComputeLabel ? '中文' : 'zh',
|
||||||
direction: 'ltr',
|
direction: 'ltr',
|
||||||
|
htmlLang: 'zh',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('zh-CN')).toEqual({
|
expect(getDefaultLocaleConfig('zh-CN')).toEqual({
|
||||||
label: canComputeLabel ? '中文(中国)' : 'zh-CN',
|
label: canComputeLabel ? '中文(中国)' : 'zh-CN',
|
||||||
direction: 'ltr',
|
direction: 'ltr',
|
||||||
|
htmlLang: 'zh-CN',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('en-US')).toEqual({
|
expect(getDefaultLocaleConfig('en-US')).toEqual({
|
||||||
label: canComputeLabel ? 'American English' : 'en-US',
|
label: canComputeLabel ? 'American English' : 'en-US',
|
||||||
direction: 'ltr',
|
direction: 'ltr',
|
||||||
|
htmlLang: 'en-US',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('fa')).toEqual({
|
expect(getDefaultLocaleConfig('fa')).toEqual({
|
||||||
label: canComputeLabel ? 'فارسی' : 'fa',
|
label: canComputeLabel ? 'فارسی' : 'fa',
|
||||||
direction: 'rtl',
|
direction: 'rtl',
|
||||||
|
htmlLang: 'fa',
|
||||||
});
|
});
|
||||||
expect(getDefaultLocaleConfig('fa-IR')).toEqual({
|
expect(getDefaultLocaleConfig('fa-IR')).toEqual({
|
||||||
label: canComputeLabel ? 'فارسی (ایران)' : 'fa-IR',
|
label: canComputeLabel ? 'فارسی (ایران)' : 'fa-IR',
|
||||||
direction: 'rtl',
|
direction: 'rtl',
|
||||||
|
htmlLang: 'fa-IR',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -156,7 +165,7 @@ describe('loadI18n', () => {
|
||||||
locales: ['en', 'fr', 'de'],
|
locales: ['en', 'fr', 'de'],
|
||||||
currentLocale: 'de',
|
currentLocale: 'de',
|
||||||
localeConfigs: {
|
localeConfigs: {
|
||||||
fr: {label: 'Français', direction: 'ltr'},
|
fr: {label: 'Français', direction: 'ltr', htmlLang: 'fr'},
|
||||||
en: getDefaultLocaleConfig('en'),
|
en: getDefaultLocaleConfig('en'),
|
||||||
de: getDefaultLocaleConfig('de'),
|
de: getDefaultLocaleConfig('de'),
|
||||||
},
|
},
|
||||||
|
|
|
@ -96,6 +96,7 @@ const PresetSchema = Joi.alternatives().try(
|
||||||
|
|
||||||
const LocaleConfigSchema = Joi.object({
|
const LocaleConfigSchema = Joi.object({
|
||||||
label: Joi.string(),
|
label: Joi.string(),
|
||||||
|
htmlLang: Joi.string(),
|
||||||
direction: Joi.string().equal('ltr', 'rtl').default('ltr'),
|
direction: Joi.string().equal('ltr', 'rtl').default('ltr'),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ export function getDefaultLocaleConfig(locale: string): I18nLocaleConfig {
|
||||||
return {
|
return {
|
||||||
label: getDefaultLocaleLabel(locale),
|
label: getDefaultLocaleLabel(locale),
|
||||||
direction: getLangDir(locale),
|
direction: getLangDir(locale),
|
||||||
|
htmlLang: locale,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue