mirror of
https://github.com/facebook/docusaurus.git
synced 2025-07-20 10:08:17 +02:00
infer translate from presence of translation dir
This commit is contained in:
parent
5cfe2c1dca
commit
fe7dba95a8
7 changed files with 91 additions and 57 deletions
5
packages/docusaurus-types/src/i18n.d.ts
vendored
5
packages/docusaurus-types/src/i18n.d.ts
vendored
|
@ -33,9 +33,8 @@ export type I18nLocaleConfig = {
|
||||||
*/
|
*/
|
||||||
path: string;
|
path: string;
|
||||||
/**
|
/**
|
||||||
* Should we run the extra translation process for this locale?
|
* Should we attempt to translate this locale?
|
||||||
* By default, we skip the translation process for the default locale,
|
* By default, it will only be run if the `./i18n/<locale>` exists.
|
||||||
* while all the other locales run it.
|
|
||||||
*/
|
*/
|
||||||
translate: boolean;
|
translate: boolean;
|
||||||
};
|
};
|
||||||
|
|
|
@ -91,7 +91,11 @@ async function getLocalesToBuild({
|
||||||
localizePath,
|
localizePath,
|
||||||
});
|
});
|
||||||
|
|
||||||
const i18n = await loadI18n(context.siteConfig);
|
const i18n = await loadI18n({
|
||||||
|
siteDir,
|
||||||
|
config: context.siteConfig,
|
||||||
|
currentLocale: context.siteConfig.i18n.defaultLocale // Awkward but ok
|
||||||
|
});
|
||||||
|
|
||||||
const locales = cliOptions.locale ?? i18n.locales;
|
const locales = cliOptions.locale ?? i18n.locales;
|
||||||
|
|
||||||
|
|
1
packages/docusaurus/src/server/__tests__/__fixtures__/load-i18n-site/i18n/de/README.md
generated
Normal file
1
packages/docusaurus/src/server/__tests__/__fixtures__/load-i18n-site/i18n/de/README.md
generated
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Since i18n/de folder exists, de locale should infer to translate = true
|
1
packages/docusaurus/src/server/__tests__/__fixtures__/load-i18n-site/i18n/fr/README.md
generated
Normal file
1
packages/docusaurus/src/server/__tests__/__fixtures__/load-i18n-site/i18n/fr/README.md
generated
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Since i18n/fr folder exists, fr locale should infer to translate = true
|
|
@ -6,17 +6,33 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {jest} from '@jest/globals';
|
import {jest} from '@jest/globals';
|
||||||
|
import path from 'path';
|
||||||
import {loadI18n, getDefaultLocaleConfig} from '../i18n';
|
import {loadI18n, getDefaultLocaleConfig} from '../i18n';
|
||||||
import {DEFAULT_I18N_CONFIG} from '../configValidation';
|
import {DEFAULT_I18N_CONFIG} from '../configValidation';
|
||||||
import type {DocusaurusConfig, I18nConfig} from '@docusaurus/types';
|
import type {DocusaurusConfig, I18nConfig} from '@docusaurus/types';
|
||||||
|
|
||||||
function loadI18nTest(i18nConfig: I18nConfig, locale?: string) {
|
const loadI18nSiteDir = path.resolve(
|
||||||
return loadI18n(
|
__dirname,
|
||||||
{
|
'__fixtures__',
|
||||||
|
'load-i18n-site',
|
||||||
|
);
|
||||||
|
|
||||||
|
function loadI18nTest({
|
||||||
|
siteDir = loadI18nSiteDir,
|
||||||
|
i18nConfig,
|
||||||
|
currentLocale,
|
||||||
|
}: {
|
||||||
|
siteDir?: string;
|
||||||
|
i18nConfig: I18nConfig;
|
||||||
|
currentLocale: string;
|
||||||
|
}) {
|
||||||
|
return loadI18n({
|
||||||
|
siteDir,
|
||||||
|
config: {
|
||||||
i18n: i18nConfig,
|
i18n: i18nConfig,
|
||||||
} as DocusaurusConfig,
|
} as DocusaurusConfig,
|
||||||
{locale},
|
currentLocale,
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('defaultLocaleConfig', () => {
|
describe('defaultLocaleConfig', () => {
|
||||||
|
@ -103,7 +119,12 @@ describe('loadI18n', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads I18n for default config', async () => {
|
it('loads I18n for default config', async () => {
|
||||||
await expect(loadI18nTest(DEFAULT_I18N_CONFIG)).resolves.toEqual({
|
await expect(
|
||||||
|
loadI18nTest({
|
||||||
|
i18nConfig: DEFAULT_I18N_CONFIG,
|
||||||
|
currentLocale: 'en',
|
||||||
|
}),
|
||||||
|
).resolves.toEqual({
|
||||||
path: 'i18n',
|
path: 'i18n',
|
||||||
defaultLocale: 'en',
|
defaultLocale: 'en',
|
||||||
locales: ['en'],
|
locales: ['en'],
|
||||||
|
@ -120,10 +141,13 @@ describe('loadI18n', () => {
|
||||||
it('loads I18n for multi-lang config', async () => {
|
it('loads I18n for multi-lang config', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
loadI18nTest({
|
loadI18nTest({
|
||||||
|
i18nConfig: {
|
||||||
path: 'i18n',
|
path: 'i18n',
|
||||||
defaultLocale: 'fr',
|
defaultLocale: 'fr',
|
||||||
locales: ['en', 'fr', 'de'],
|
locales: ['en', 'fr', 'de'],
|
||||||
localeConfigs: {},
|
localeConfigs: {},
|
||||||
|
},
|
||||||
|
currentLocale: 'fr',
|
||||||
}),
|
}),
|
||||||
).resolves.toEqual({
|
).resolves.toEqual({
|
||||||
defaultLocale: 'fr',
|
defaultLocale: 'fr',
|
||||||
|
@ -133,11 +157,11 @@ describe('loadI18n', () => {
|
||||||
localeConfigs: {
|
localeConfigs: {
|
||||||
en: {
|
en: {
|
||||||
...getDefaultLocaleConfig('en'),
|
...getDefaultLocaleConfig('en'),
|
||||||
translate: true,
|
translate: false,
|
||||||
},
|
},
|
||||||
fr: {
|
fr: {
|
||||||
...getDefaultLocaleConfig('fr'),
|
...getDefaultLocaleConfig('fr'),
|
||||||
translate: false,
|
translate: true,
|
||||||
},
|
},
|
||||||
de: {
|
de: {
|
||||||
...getDefaultLocaleConfig('de'),
|
...getDefaultLocaleConfig('de'),
|
||||||
|
@ -149,15 +173,15 @@ describe('loadI18n', () => {
|
||||||
|
|
||||||
it('loads I18n for multi-locale config with specified locale', async () => {
|
it('loads I18n for multi-locale config with specified locale', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
loadI18nTest(
|
loadI18nTest({
|
||||||
{
|
i18nConfig: {
|
||||||
path: 'i18n',
|
path: 'i18n',
|
||||||
defaultLocale: 'fr',
|
defaultLocale: 'fr',
|
||||||
locales: ['en', 'fr', 'de'],
|
locales: ['en', 'fr', 'de'],
|
||||||
localeConfigs: {},
|
localeConfigs: {},
|
||||||
},
|
},
|
||||||
'de',
|
currentLocale: 'de',
|
||||||
),
|
}),
|
||||||
).resolves.toEqual({
|
).resolves.toEqual({
|
||||||
defaultLocale: 'fr',
|
defaultLocale: 'fr',
|
||||||
path: 'i18n',
|
path: 'i18n',
|
||||||
|
@ -166,11 +190,11 @@ describe('loadI18n', () => {
|
||||||
localeConfigs: {
|
localeConfigs: {
|
||||||
en: {
|
en: {
|
||||||
...getDefaultLocaleConfig('en'),
|
...getDefaultLocaleConfig('en'),
|
||||||
translate: true,
|
translate: false,
|
||||||
},
|
},
|
||||||
fr: {
|
fr: {
|
||||||
...getDefaultLocaleConfig('fr'),
|
...getDefaultLocaleConfig('fr'),
|
||||||
translate: false,
|
translate: true,
|
||||||
},
|
},
|
||||||
de: {
|
de: {
|
||||||
...getDefaultLocaleConfig('de'),
|
...getDefaultLocaleConfig('de'),
|
||||||
|
@ -182,19 +206,19 @@ describe('loadI18n', () => {
|
||||||
|
|
||||||
it('loads I18n for multi-locale config with some custom locale configs', async () => {
|
it('loads I18n for multi-locale config with some custom locale configs', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
loadI18nTest(
|
loadI18nTest({
|
||||||
{
|
i18nConfig: {
|
||||||
path: 'i18n',
|
path: 'i18n',
|
||||||
defaultLocale: 'fr',
|
defaultLocale: 'fr',
|
||||||
locales: ['en', 'fr', 'de'],
|
locales: ['en', 'fr', 'de'],
|
||||||
localeConfigs: {
|
localeConfigs: {
|
||||||
fr: {label: 'Français', translate: false},
|
fr: {label: 'Français', translate: false},
|
||||||
en: {},
|
en: {translate: true},
|
||||||
de: {translate: false},
|
de: {translate: false},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'de',
|
currentLocale: 'de',
|
||||||
),
|
}),
|
||||||
).resolves.toEqual({
|
).resolves.toEqual({
|
||||||
defaultLocale: 'fr',
|
defaultLocale: 'fr',
|
||||||
path: 'i18n',
|
path: 'i18n',
|
||||||
|
@ -222,15 +246,15 @@ describe('loadI18n', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('warns when trying to load undeclared locale', async () => {
|
it('warns when trying to load undeclared locale', async () => {
|
||||||
await loadI18nTest(
|
await loadI18nTest({
|
||||||
{
|
i18nConfig: {
|
||||||
path: 'i18n',
|
path: 'i18n',
|
||||||
defaultLocale: 'fr',
|
defaultLocale: 'fr',
|
||||||
locales: ['en', 'fr', 'de'],
|
locales: ['en', 'fr', 'de'],
|
||||||
localeConfigs: {},
|
localeConfigs: {},
|
||||||
},
|
},
|
||||||
'it',
|
currentLocale: 'it',
|
||||||
);
|
});
|
||||||
expect(consoleSpy.mock.calls[0]![0]).toMatch(
|
expect(consoleSpy.mock.calls[0]![0]).toMatch(
|
||||||
/The locale .*it.* was not found in your site configuration/,
|
/The locale .*it.* was not found in your site configuration/,
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,10 +5,11 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import path from 'path';
|
||||||
|
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 type {I18n, DocusaurusConfig, I18nLocaleConfig} from '@docusaurus/types';
|
import type {I18n, DocusaurusConfig, I18nLocaleConfig} from '@docusaurus/types';
|
||||||
import type {LoadContextParams} from './site';
|
|
||||||
|
|
||||||
function inferLanguageDisplayName(locale: string) {
|
function inferLanguageDisplayName(locale: string) {
|
||||||
const tryLocale = (l: string) => {
|
const tryLocale = (l: string) => {
|
||||||
|
@ -98,27 +99,17 @@ export function getDefaultLocaleConfig(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function shouldTranslateLocale({
|
export async function loadI18n({
|
||||||
locale,
|
siteDir,
|
||||||
defaultLocale,
|
config,
|
||||||
localeConfigInput,
|
currentLocale,
|
||||||
}: {
|
}: {
|
||||||
locale: string;
|
siteDir: string;
|
||||||
defaultLocale: string;
|
config: DocusaurusConfig;
|
||||||
localeConfigInput: Partial<I18nLocaleConfig>;
|
currentLocale: string;
|
||||||
}): Promise<boolean> {
|
}): Promise<I18n> {
|
||||||
// Maybe in the future we want to check if `./i18n/en` exists?
|
|
||||||
return localeConfigInput.translate ?? locale !== defaultLocale;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function loadI18n(
|
|
||||||
config: DocusaurusConfig,
|
|
||||||
options?: Pick<LoadContextParams, 'locale'>,
|
|
||||||
): Promise<I18n> {
|
|
||||||
const {i18n: i18nConfig} = config;
|
const {i18n: i18nConfig} = config;
|
||||||
|
|
||||||
const currentLocale = options?.locale ?? i18nConfig.defaultLocale;
|
|
||||||
|
|
||||||
if (!i18nConfig.locales.includes(currentLocale)) {
|
if (!i18nConfig.locales.includes(currentLocale)) {
|
||||||
logger.warn`The locale name=${currentLocale} was not found in your site configuration: Available locales are: ${i18nConfig.locales}
|
logger.warn`The locale name=${currentLocale} was not found in your site configuration: Available locales are: ${i18nConfig.locales}
|
||||||
Note: Docusaurus only support running one locale at a time.`;
|
Note: Docusaurus only support running one locale at a time.`;
|
||||||
|
@ -132,14 +123,24 @@ 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 translate = await shouldTranslateLocale({
|
const localeConfig: Omit<I18nLocaleConfig, 'translate'> = {
|
||||||
locale,
|
|
||||||
defaultLocale: i18nConfig.defaultLocale,
|
|
||||||
localeConfigInput,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
...getDefaultLocaleConfig(locale),
|
...getDefaultLocaleConfig(locale),
|
||||||
...localeConfigInput,
|
...localeConfigInput,
|
||||||
|
};
|
||||||
|
|
||||||
|
// By default, translations will be enabled if i18n/<locale> dir exists
|
||||||
|
async function inferTranslate() {
|
||||||
|
const localizationDir = path.resolve(
|
||||||
|
siteDir,
|
||||||
|
i18nConfig.path,
|
||||||
|
localeConfig.path,
|
||||||
|
);
|
||||||
|
return fs.pathExists(localizationDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
const translate = localeConfigInput.translate ?? (await inferTranslate());
|
||||||
|
return {
|
||||||
|
...localeConfig,
|
||||||
translate,
|
translate,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,11 @@ export async function loadContext(
|
||||||
siteConfig: initialSiteConfig,
|
siteConfig: initialSiteConfig,
|
||||||
});
|
});
|
||||||
|
|
||||||
const i18n = await loadI18n(initialSiteConfig, {locale});
|
const i18n = await loadI18n({
|
||||||
|
siteDir,
|
||||||
|
config: initialSiteConfig,
|
||||||
|
currentLocale: locale ?? initialSiteConfig.i18n.defaultLocale,
|
||||||
|
});
|
||||||
|
|
||||||
const baseUrl = localizePath({
|
const baseUrl = localizePath({
|
||||||
path: initialSiteConfig.baseUrl,
|
path: initialSiteConfig.baseUrl,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue