Make it possible to infer locale config from the htmlLang attribute, to support cases where the locale name is not BCP 47

This commit is contained in:
sebastien 2025-11-14 12:37:18 +01:00
parent 74398e04d3
commit 7eb099c7f2
2 changed files with 70 additions and 6 deletions

View File

@ -123,9 +123,11 @@ describe('defaultLocaleConfig', () => {
});
describe('loadI18n', () => {
const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
const consoleWarnSpy = jest
.spyOn(console, 'warn')
.mockImplementation(() => {});
beforeEach(() => {
consoleSpy.mockClear();
consoleWarnSpy.mockClear();
});
it('loads I18n for default config', async () => {
@ -397,8 +399,67 @@ describe('loadI18n', () => {
},
currentLocale: 'it',
});
expect(consoleSpy.mock.calls[0]![0]).toMatch(
expect(consoleWarnSpy.mock.calls[0]![0]).toMatch(
/The locale .*it.* was not found in your Docusaurus site configuration/,
);
});
it('throws when trying to load undeclared locale that is not a valid locale BCP47 name', async () => {
await expect(() =>
loadI18nTest({
i18nConfig: {
path: 'i18n',
defaultLocale: 'fr',
locales: ['en', 'fr', 'de'],
localeConfigs: {},
},
currentLocale: 'x1',
}),
).rejects.toThrowErrorMatchingInlineSnapshot(`
"Docusaurus couldn't infer a default locale config for x1.
Make sure it is a valid BCP 47 locale name (e.g. en, fr, fr-FR, etc.) and/or provide a valid BCP 47 \`siteConfig.i18n.localeConfig['x1'].htmlLang\` attribute."
`);
});
it('throws when trying to load declared locale that is not a valid locale BCP47 name', async () => {
await expect(() =>
loadI18nTest({
i18nConfig: {
path: 'i18n',
defaultLocale: 'fr',
locales: ['en', 'fr', 'de'],
localeConfigs: {x1: {}},
},
currentLocale: 'x1',
}),
).rejects.toThrowErrorMatchingInlineSnapshot(`
"Docusaurus couldn't infer a default locale config for x1.
Make sure it is a valid BCP 47 locale name (e.g. en, fr, fr-FR, etc.) and/or provide a valid BCP 47 \`siteConfig.i18n.localeConfig['x1'].htmlLang\` attribute."
`);
});
it('loads i18n when trying to load declared locale with invalid BCP47 name but valid BCP47', async () => {
const result = await loadI18nTest({
i18nConfig: {
path: 'i18n',
defaultLocale: 'fr',
locales: ['en', 'x1'],
localeConfigs: {
x1: {htmlLang: 'en-US'},
},
},
currentLocale: 'x1',
});
expect(result.localeConfigs.x1).toEqual({
baseUrl: '/x1/',
calendar: 'gregory',
direction: 'ltr',
htmlLang: 'en-US',
label: 'American English',
path: 'en-US',
translate: false,
url: 'https://example.com',
});
expect(consoleWarnSpy).toHaveBeenCalledTimes(0);
});
});

View File

@ -100,9 +100,12 @@ export function getDefaultLocaleConfig(
};
} catch (e) {
throw new Error(
`Docusaurus couldn't get default locale config for ${logger.name(
`Docusaurus couldn't infer a default locale config for ${logger.name(
locale,
)}`,
)}.
Make sure it is a valid BCP 47 locale name (e.g. en, fr, fr-FR, etc.) and/or provide a valid BCP 47 ${logger.code(
`siteConfig.i18n.localeConfig['${locale}'].htmlLang`,
)} attribute.`,
{cause: e},
);
}
@ -150,7 +153,7 @@ export async function loadI18n({
I18nLocaleConfig,
'translate' | 'url' | 'baseUrl'
> = {
...getDefaultLocaleConfig(locale),
...getDefaultLocaleConfig(localeConfigInput.htmlLang ?? locale),
...localeConfigInput,
};