mirror of
https://github.com/facebook/docusaurus.git
synced 2025-07-18 17:17:57 +02:00
Merge cc08a46b66
into a3324ff65e
This commit is contained in:
commit
5eb873b45e
3 changed files with 91 additions and 4 deletions
15
packages/docusaurus-types/src/i18n.d.ts
vendored
15
packages/docusaurus-types/src/i18n.d.ts
vendored
|
@ -37,6 +37,21 @@ export type I18nLocaleConfig = {
|
||||||
* By default, it will only be run if the `./i18n/<locale>` exists.
|
* By default, it will only be run if the `./i18n/<locale>` exists.
|
||||||
*/
|
*/
|
||||||
translate: boolean;
|
translate: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The baseUrl to use for this locale.
|
||||||
|
* This overrides the `siteConfig.baseUrl` attribute.
|
||||||
|
*
|
||||||
|
* Default values:
|
||||||
|
* - Default locale: `/${siteConfig.baseUrl}/`
|
||||||
|
* - Other locales: `/${siteConfig.baseUrl}/<locale>/`
|
||||||
|
*
|
||||||
|
* Exception: when using the CLI with a single `--locale` parameter, the
|
||||||
|
* `/<locale>/` path segment is not included. This is a better default for
|
||||||
|
* sites looking to deploy each locale to a different subdomain, such as
|
||||||
|
* `https://<locale>.docusaurus.io`
|
||||||
|
*/
|
||||||
|
baseUrl: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type I18nConfig = {
|
export type I18nConfig = {
|
||||||
|
|
|
@ -19,10 +19,12 @@ const loadI18nSiteDir = path.resolve(
|
||||||
|
|
||||||
function loadI18nTest({
|
function loadI18nTest({
|
||||||
siteDir = loadI18nSiteDir,
|
siteDir = loadI18nSiteDir,
|
||||||
|
baseUrl = '/',
|
||||||
i18nConfig,
|
i18nConfig,
|
||||||
currentLocale,
|
currentLocale,
|
||||||
}: {
|
}: {
|
||||||
siteDir?: string;
|
siteDir?: string;
|
||||||
|
baseUrl?: string;
|
||||||
i18nConfig: I18nConfig;
|
i18nConfig: I18nConfig;
|
||||||
currentLocale: string;
|
currentLocale: string;
|
||||||
}) {
|
}) {
|
||||||
|
@ -30,6 +32,7 @@ function loadI18nTest({
|
||||||
siteDir,
|
siteDir,
|
||||||
config: {
|
config: {
|
||||||
i18n: i18nConfig,
|
i18n: i18nConfig,
|
||||||
|
baseUrl,
|
||||||
} as DocusaurusConfig,
|
} as DocusaurusConfig,
|
||||||
currentLocale,
|
currentLocale,
|
||||||
});
|
});
|
||||||
|
@ -133,6 +136,7 @@ describe('loadI18n', () => {
|
||||||
en: {
|
en: {
|
||||||
...getDefaultLocaleConfig('en'),
|
...getDefaultLocaleConfig('en'),
|
||||||
translate: false,
|
translate: false,
|
||||||
|
baseUrl: '/',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -158,14 +162,17 @@ describe('loadI18n', () => {
|
||||||
en: {
|
en: {
|
||||||
...getDefaultLocaleConfig('en'),
|
...getDefaultLocaleConfig('en'),
|
||||||
translate: false,
|
translate: false,
|
||||||
|
baseUrl: '/en/',
|
||||||
},
|
},
|
||||||
fr: {
|
fr: {
|
||||||
...getDefaultLocaleConfig('fr'),
|
...getDefaultLocaleConfig('fr'),
|
||||||
translate: true,
|
translate: true,
|
||||||
|
baseUrl: '/',
|
||||||
},
|
},
|
||||||
de: {
|
de: {
|
||||||
...getDefaultLocaleConfig('de'),
|
...getDefaultLocaleConfig('de'),
|
||||||
translate: true,
|
translate: true,
|
||||||
|
baseUrl: '/de/',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -191,14 +198,17 @@ describe('loadI18n', () => {
|
||||||
en: {
|
en: {
|
||||||
...getDefaultLocaleConfig('en'),
|
...getDefaultLocaleConfig('en'),
|
||||||
translate: false,
|
translate: false,
|
||||||
|
baseUrl: '/en/',
|
||||||
},
|
},
|
||||||
fr: {
|
fr: {
|
||||||
...getDefaultLocaleConfig('fr'),
|
...getDefaultLocaleConfig('fr'),
|
||||||
translate: true,
|
translate: true,
|
||||||
|
baseUrl: '/',
|
||||||
},
|
},
|
||||||
de: {
|
de: {
|
||||||
...getDefaultLocaleConfig('de'),
|
...getDefaultLocaleConfig('de'),
|
||||||
translate: true,
|
translate: true,
|
||||||
|
baseUrl: '/de/',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -213,10 +223,11 @@ describe('loadI18n', () => {
|
||||||
locales: ['en', 'fr', 'de'],
|
locales: ['en', 'fr', 'de'],
|
||||||
localeConfigs: {
|
localeConfigs: {
|
||||||
fr: {label: 'Français', translate: false},
|
fr: {label: 'Français', translate: false},
|
||||||
en: {translate: true},
|
en: {translate: true, baseUrl: 'en-EN/whatever/else'},
|
||||||
de: {translate: false},
|
de: {translate: false, baseUrl: '/de-DE/'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
currentLocale: 'de',
|
currentLocale: 'de',
|
||||||
}),
|
}),
|
||||||
).resolves.toEqual({
|
).resolves.toEqual({
|
||||||
|
@ -232,19 +243,58 @@ describe('loadI18n', () => {
|
||||||
calendar: 'gregory',
|
calendar: 'gregory',
|
||||||
path: 'fr',
|
path: 'fr',
|
||||||
translate: false,
|
translate: false,
|
||||||
|
baseUrl: '/',
|
||||||
},
|
},
|
||||||
en: {
|
en: {
|
||||||
...getDefaultLocaleConfig('en'),
|
...getDefaultLocaleConfig('en'),
|
||||||
translate: true,
|
translate: true,
|
||||||
|
baseUrl: '/en-EN/whatever/else/',
|
||||||
},
|
},
|
||||||
de: {
|
de: {
|
||||||
...getDefaultLocaleConfig('de'),
|
...getDefaultLocaleConfig('de'),
|
||||||
translate: false,
|
translate: false,
|
||||||
|
baseUrl: '/de-DE/',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('loads I18n for multi-locale config with baseUrl edge cases', async () => {
|
||||||
|
await expect(
|
||||||
|
loadI18nTest({
|
||||||
|
baseUrl: 'siteBaseUrl',
|
||||||
|
i18nConfig: {
|
||||||
|
path: 'i18n',
|
||||||
|
defaultLocale: 'fr',
|
||||||
|
locales: ['en', 'fr', 'de', 'pt'],
|
||||||
|
localeConfigs: {
|
||||||
|
fr: {},
|
||||||
|
en: {baseUrl: ''},
|
||||||
|
de: {baseUrl: '/de-DE/'},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
currentLocale: 'de',
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
localeConfigs: {
|
||||||
|
fr: expect.objectContaining({
|
||||||
|
baseUrl: '/siteBaseUrl/',
|
||||||
|
}),
|
||||||
|
en: expect.objectContaining({
|
||||||
|
baseUrl: '/',
|
||||||
|
}),
|
||||||
|
de: expect.objectContaining({
|
||||||
|
baseUrl: '/de-DE/',
|
||||||
|
}),
|
||||||
|
pt: expect.objectContaining({
|
||||||
|
baseUrl: '/siteBaseUrl/pt/',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('warns when trying to load undeclared locale', async () => {
|
it('warns when trying to load undeclared locale', async () => {
|
||||||
await loadI18nTest({
|
await loadI18nTest({
|
||||||
i18nConfig: {
|
i18nConfig: {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import path from 'path';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import logger from '@docusaurus/logger';
|
import logger from '@docusaurus/logger';
|
||||||
import combinePromises from 'combine-promises';
|
import combinePromises from 'combine-promises';
|
||||||
|
import {normalizeUrl} from '@docusaurus/utils';
|
||||||
import type {I18n, DocusaurusConfig, I18nLocaleConfig} from '@docusaurus/types';
|
import type {I18n, DocusaurusConfig, I18nLocaleConfig} from '@docusaurus/types';
|
||||||
|
|
||||||
function inferLanguageDisplayName(locale: string) {
|
function inferLanguageDisplayName(locale: string) {
|
||||||
|
@ -82,7 +83,7 @@ function getDefaultDirection(localeStr: string) {
|
||||||
|
|
||||||
export function getDefaultLocaleConfig(
|
export function getDefaultLocaleConfig(
|
||||||
locale: string,
|
locale: string,
|
||||||
): Omit<I18nLocaleConfig, 'translate'> {
|
): Omit<I18nLocaleConfig, 'translate' | 'baseUrl'> {
|
||||||
try {
|
try {
|
||||||
return {
|
return {
|
||||||
label: getDefaultLocaleLabel(locale),
|
label: getDefaultLocaleLabel(locale),
|
||||||
|
@ -123,7 +124,7 @@ Note: Docusaurus only support running one locale at a time.`;
|
||||||
locale: string,
|
locale: string,
|
||||||
): Promise<I18nLocaleConfig> {
|
): Promise<I18nLocaleConfig> {
|
||||||
const localeConfigInput = i18nConfig.localeConfigs[locale] ?? {};
|
const localeConfigInput = i18nConfig.localeConfigs[locale] ?? {};
|
||||||
const localeConfig: Omit<I18nLocaleConfig, 'translate'> = {
|
const localeConfig: Omit<I18nLocaleConfig, 'translate' | 'baseUrl'> = {
|
||||||
...getDefaultLocaleConfig(locale),
|
...getDefaultLocaleConfig(locale),
|
||||||
...localeConfigInput,
|
...localeConfigInput,
|
||||||
};
|
};
|
||||||
|
@ -138,10 +139,31 @@ Note: Docusaurus only support running one locale at a time.`;
|
||||||
return fs.pathExists(localizationDir);
|
return fs.pathExists(localizationDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getBaseUrl(): string {
|
||||||
|
if (typeof localeConfigInput.baseUrl !== 'undefined') {
|
||||||
|
return normalizeUrl(['/', localeConfigInput.baseUrl, '/']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO CLI locales.length === 1 case - retro compat
|
||||||
|
const hasLocaleSegment = locale !== i18nConfig.defaultLocale;
|
||||||
|
|
||||||
|
return normalizeUrl([
|
||||||
|
'/',
|
||||||
|
config.baseUrl,
|
||||||
|
hasLocaleSegment ? locale : '',
|
||||||
|
'/',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
const translate = localeConfigInput.translate ?? (await inferTranslate());
|
const translate = localeConfigInput.translate ?? (await inferTranslate());
|
||||||
|
const baseUrl =
|
||||||
|
typeof localeConfigInput.baseUrl !== 'undefined'
|
||||||
|
? normalizeUrl(['/', localeConfigInput.baseUrl, '/'])
|
||||||
|
: getBaseUrl();
|
||||||
return {
|
return {
|
||||||
...localeConfig,
|
...localeConfig,
|
||||||
translate,
|
translate,
|
||||||
|
baseUrl,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue