mirror of
https://github.com/facebook/docusaurus.git
synced 2025-08-02 16:29:47 +02:00
feat(core): allow customizing the i18n directory path (#7386)
Co-authored-by: sebastienlorber <lorber.sebastien@gmail.com>
This commit is contained in:
parent
c07a514730
commit
abe5450526
26 changed files with 147 additions and 166 deletions
|
@ -25,7 +25,6 @@ import {
|
|||
getHttpsConfig,
|
||||
} from '../webpack/utils';
|
||||
import {getHostPort, type HostPortOptions} from '../server/getHostPort';
|
||||
import {getTranslationsLocaleDirPath} from '../server/translations/translations';
|
||||
|
||||
export type StartCLIOptions = HostPortOptions &
|
||||
Pick<LoadContextOptions, 'locale' | 'config'> & {
|
||||
|
@ -82,7 +81,7 @@ export async function start(
|
|||
logger.error(err.stack);
|
||||
});
|
||||
}, 500);
|
||||
const {siteConfig, plugins} = props;
|
||||
const {siteConfig, plugins, localizationDir} = props;
|
||||
|
||||
const normalizeToSiteDir = (filepath: string) => {
|
||||
if (filepath && path.isAbsolute(filepath)) {
|
||||
|
@ -96,14 +95,7 @@ export async function start(
|
|||
.filter(Boolean)
|
||||
.map(normalizeToSiteDir);
|
||||
|
||||
const pathsToWatch = [
|
||||
...pluginPaths,
|
||||
props.siteConfigPath,
|
||||
getTranslationsLocaleDirPath({
|
||||
siteDir,
|
||||
locale: props.i18n.currentLocale,
|
||||
}),
|
||||
];
|
||||
const pathsToWatch = [...pluginPaths, props.siteConfigPath, localizationDir];
|
||||
|
||||
const pollingOptions = {
|
||||
usePolling: !!cliOptions.poll,
|
||||
|
|
|
@ -47,14 +47,12 @@ async function getExtraSourceCodeFilePaths(): Promise<string[]> {
|
|||
}
|
||||
|
||||
async function writePluginTranslationFiles({
|
||||
siteDir,
|
||||
localizationDir,
|
||||
plugin,
|
||||
locale,
|
||||
options,
|
||||
}: {
|
||||
siteDir: string;
|
||||
localizationDir: string;
|
||||
plugin: InitializedPlugin;
|
||||
locale: string;
|
||||
options: WriteTranslationsOptions;
|
||||
}) {
|
||||
if (plugin.getTranslationFiles) {
|
||||
|
@ -66,10 +64,9 @@ async function writePluginTranslationFiles({
|
|||
await Promise.all(
|
||||
translationFiles.map(async (translationFile) => {
|
||||
await writePluginTranslations({
|
||||
siteDir,
|
||||
localizationDir,
|
||||
plugin,
|
||||
translationFile,
|
||||
locale,
|
||||
options,
|
||||
});
|
||||
}),
|
||||
|
@ -86,6 +83,7 @@ export async function writeTranslations(
|
|||
config: options.config,
|
||||
locale: options.locale,
|
||||
});
|
||||
const {localizationDir} = context;
|
||||
const plugins = await initPlugins(context);
|
||||
|
||||
const locale = options.locale ?? context.i18n.defaultLocale;
|
||||
|
@ -116,11 +114,11 @@ Available locales are: ${context.i18n.locales.join(',')}.`,
|
|||
defaultCodeMessages,
|
||||
});
|
||||
|
||||
await writeCodeTranslations({siteDir, locale}, codeTranslations, options);
|
||||
await writeCodeTranslations({localizationDir}, codeTranslations, options);
|
||||
|
||||
await Promise.all(
|
||||
plugins.map(async (plugin) => {
|
||||
await writePluginTranslationFiles({siteDir, plugin, locale, options});
|
||||
await writePluginTranslationFiles({localizationDir, plugin, options});
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ exports[`loadSiteConfig website with .cjs siteConfig 1`] = `
|
|||
"locales": [
|
||||
"en",
|
||||
],
|
||||
"path": "i18n",
|
||||
},
|
||||
"noIndex": false,
|
||||
"onBrokenLinks": "throw",
|
||||
|
@ -49,6 +50,7 @@ exports[`loadSiteConfig website with valid async config 1`] = `
|
|||
"locales": [
|
||||
"en",
|
||||
],
|
||||
"path": "i18n",
|
||||
},
|
||||
"noIndex": false,
|
||||
"onBrokenLinks": "throw",
|
||||
|
@ -87,6 +89,7 @@ exports[`loadSiteConfig website with valid async config creator function 1`] = `
|
|||
"locales": [
|
||||
"en",
|
||||
],
|
||||
"path": "i18n",
|
||||
},
|
||||
"noIndex": false,
|
||||
"onBrokenLinks": "throw",
|
||||
|
@ -125,6 +128,7 @@ exports[`loadSiteConfig website with valid config creator function 1`] = `
|
|||
"locales": [
|
||||
"en",
|
||||
],
|
||||
"path": "i18n",
|
||||
},
|
||||
"noIndex": false,
|
||||
"onBrokenLinks": "throw",
|
||||
|
@ -166,6 +170,7 @@ exports[`loadSiteConfig website with valid siteConfig 1`] = `
|
|||
"locales": [
|
||||
"en",
|
||||
],
|
||||
"path": "i18n",
|
||||
},
|
||||
"noIndex": false,
|
||||
"onBrokenLinks": "throw",
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import {jest} from '@jest/globals';
|
||||
import {loadI18n, getDefaultLocaleConfig} from '../i18n';
|
||||
import {DEFAULT_I18N_CONFIG} from '../configValidation';
|
||||
import type {I18nConfig} from '@docusaurus/types';
|
||||
import type {DocusaurusConfig, I18nConfig} from '@docusaurus/types';
|
||||
|
||||
function testLocaleConfigsFor(locales: string[]) {
|
||||
return Object.fromEntries(
|
||||
|
@ -18,10 +18,9 @@ function testLocaleConfigsFor(locales: string[]) {
|
|||
|
||||
function loadI18nTest(i18nConfig: I18nConfig, locale?: string) {
|
||||
return loadI18n(
|
||||
// @ts-expect-error: enough for this test
|
||||
{
|
||||
i18n: i18nConfig,
|
||||
},
|
||||
} as DocusaurusConfig,
|
||||
{locale},
|
||||
);
|
||||
}
|
||||
|
@ -101,6 +100,7 @@ describe('loadI18n', () => {
|
|||
|
||||
it('loads I18n for default config', async () => {
|
||||
await expect(loadI18nTest(DEFAULT_I18N_CONFIG)).resolves.toEqual({
|
||||
path: 'i18n',
|
||||
defaultLocale: 'en',
|
||||
locales: ['en'],
|
||||
currentLocale: 'en',
|
||||
|
@ -111,12 +111,14 @@ describe('loadI18n', () => {
|
|||
it('loads I18n for multi-lang config', async () => {
|
||||
await expect(
|
||||
loadI18nTest({
|
||||
path: 'i18n',
|
||||
defaultLocale: 'fr',
|
||||
locales: ['en', 'fr', 'de'],
|
||||
localeConfigs: {},
|
||||
}),
|
||||
).resolves.toEqual({
|
||||
defaultLocale: 'fr',
|
||||
path: 'i18n',
|
||||
locales: ['en', 'fr', 'de'],
|
||||
currentLocale: 'fr',
|
||||
localeConfigs: testLocaleConfigsFor(['en', 'fr', 'de']),
|
||||
|
@ -127,6 +129,7 @@ describe('loadI18n', () => {
|
|||
await expect(
|
||||
loadI18nTest(
|
||||
{
|
||||
path: 'i18n',
|
||||
defaultLocale: 'fr',
|
||||
locales: ['en', 'fr', 'de'],
|
||||
localeConfigs: {},
|
||||
|
@ -135,6 +138,7 @@ describe('loadI18n', () => {
|
|||
),
|
||||
).resolves.toEqual({
|
||||
defaultLocale: 'fr',
|
||||
path: 'i18n',
|
||||
locales: ['en', 'fr', 'de'],
|
||||
currentLocale: 'de',
|
||||
localeConfigs: testLocaleConfigsFor(['en', 'fr', 'de']),
|
||||
|
@ -145,6 +149,7 @@ describe('loadI18n', () => {
|
|||
await expect(
|
||||
loadI18nTest(
|
||||
{
|
||||
path: 'i18n',
|
||||
defaultLocale: 'fr',
|
||||
locales: ['en', 'fr', 'de'],
|
||||
localeConfigs: {
|
||||
|
@ -156,6 +161,7 @@ describe('loadI18n', () => {
|
|||
),
|
||||
).resolves.toEqual({
|
||||
defaultLocale: 'fr',
|
||||
path: 'i18n',
|
||||
locales: ['en', 'fr', 'de'],
|
||||
currentLocale: 'de',
|
||||
localeConfigs: {
|
||||
|
@ -174,6 +180,7 @@ describe('loadI18n', () => {
|
|||
it('warns when trying to load undeclared locale', async () => {
|
||||
await loadI18nTest(
|
||||
{
|
||||
path: 'i18n',
|
||||
defaultLocale: 'fr',
|
||||
locales: ['en', 'fr', 'de'],
|
||||
localeConfigs: {},
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {DEFAULT_STATIC_DIR_NAME} from '@docusaurus/utils';
|
||||
import {
|
||||
DEFAULT_STATIC_DIR_NAME,
|
||||
DEFAULT_I18N_DIR_NAME,
|
||||
} from '@docusaurus/utils';
|
||||
import {Joi, URISchema, printWarning} from '@docusaurus/utils-validation';
|
||||
import type {DocusaurusConfig, I18nConfig} from '@docusaurus/types';
|
||||
|
||||
|
@ -13,6 +16,7 @@ const DEFAULT_I18N_LOCALE = 'en';
|
|||
|
||||
export const DEFAULT_I18N_CONFIG: I18nConfig = {
|
||||
defaultLocale: DEFAULT_I18N_LOCALE,
|
||||
path: DEFAULT_I18N_DIR_NAME,
|
||||
locales: [DEFAULT_I18N_LOCALE],
|
||||
localeConfigs: {},
|
||||
};
|
||||
|
@ -135,6 +139,7 @@ const LocaleConfigSchema = Joi.object({
|
|||
|
||||
const I18N_CONFIG_SCHEMA = Joi.object<I18nConfig>({
|
||||
defaultLocale: Joi.string().required(),
|
||||
path: Joi.string().default(DEFAULT_I18N_CONFIG.path),
|
||||
locales: Joi.array().items().min(1).items(Joi.string().required()).required(),
|
||||
localeConfigs: Joi.object()
|
||||
.pattern(/.*/, LocaleConfigSchema)
|
||||
|
|
|
@ -60,6 +60,7 @@ Note: Docusaurus only support running one locale at a time.`;
|
|||
return {
|
||||
defaultLocale: i18nConfig.defaultLocale,
|
||||
locales,
|
||||
path: i18nConfig.path,
|
||||
currentLocale,
|
||||
localeConfigs,
|
||||
};
|
||||
|
|
|
@ -85,11 +85,11 @@ export async function loadContext(
|
|||
|
||||
const siteConfig: DocusaurusConfig = {...initialSiteConfig, baseUrl};
|
||||
|
||||
// TODO allow customizing localizationDir per-locale
|
||||
const localizationDir = path.resolve(siteDir, i18n.path, i18n.currentLocale);
|
||||
|
||||
const codeTranslationFileContent =
|
||||
(await readCodeTranslationFileContent({
|
||||
siteDir,
|
||||
locale: i18n.currentLocale,
|
||||
})) ?? {};
|
||||
(await readCodeTranslationFileContent({localizationDir})) ?? {};
|
||||
|
||||
// We only need key->message for code translations
|
||||
const codeTranslations = _.mapValues(
|
||||
|
@ -100,6 +100,7 @@ export async function loadContext(
|
|||
return {
|
||||
siteDir,
|
||||
generatedFilesDir,
|
||||
localizationDir,
|
||||
siteConfig,
|
||||
siteConfigPath,
|
||||
outDir,
|
||||
|
@ -125,6 +126,7 @@ export async function load(options: LoadContextOptions): Promise<Props> {
|
|||
outDir,
|
||||
baseUrl,
|
||||
i18n,
|
||||
localizationDir,
|
||||
codeTranslations: siteCodeTranslations,
|
||||
} = context;
|
||||
const {plugins, pluginsRouteConfigs, globalData} = await loadPlugins(context);
|
||||
|
@ -246,6 +248,7 @@ ${Object.entries(registry)
|
|||
outDir,
|
||||
baseUrl,
|
||||
i18n,
|
||||
localizationDir,
|
||||
generatedFilesDir,
|
||||
routes: pluginsRouteConfigs,
|
||||
routesPaths,
|
||||
|
|
|
@ -56,8 +56,7 @@ export async function loadPlugins(context: LoadContext): Promise<{
|
|||
const translationFiles = await Promise.all(
|
||||
rawTranslationFiles.map((translationFile) =>
|
||||
localizePluginTranslationFile({
|
||||
locale: context.i18n.currentLocale,
|
||||
siteDir: context.siteDir,
|
||||
localizationDir: context.localizationDir,
|
||||
translationFile,
|
||||
plugin,
|
||||
}),
|
||||
|
|
|
@ -44,8 +44,10 @@ async function createTmpTranslationFile(
|
|||
}
|
||||
|
||||
return {
|
||||
siteDir,
|
||||
readFile: () => fs.readJSON(filePath),
|
||||
localizationDir: path.join(siteDir, 'i18n/en'),
|
||||
readFile() {
|
||||
return fs.readJSON(filePath);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -58,9 +60,9 @@ describe('writeCodeTranslations', () => {
|
|||
});
|
||||
|
||||
it('creates new translation file', async () => {
|
||||
const {siteDir, readFile} = await createTmpTranslationFile(null);
|
||||
const {localizationDir, readFile} = await createTmpTranslationFile(null);
|
||||
await writeCodeTranslations(
|
||||
{siteDir, locale: 'en'},
|
||||
{localizationDir},
|
||||
{
|
||||
key1: {message: 'key1 message'},
|
||||
key2: {message: 'key2 message'},
|
||||
|
@ -80,9 +82,9 @@ describe('writeCodeTranslations', () => {
|
|||
});
|
||||
|
||||
it('creates new translation file with prefix', async () => {
|
||||
const {siteDir, readFile} = await createTmpTranslationFile(null);
|
||||
const {localizationDir, readFile} = await createTmpTranslationFile(null);
|
||||
await writeCodeTranslations(
|
||||
{siteDir, locale: 'en'},
|
||||
{localizationDir},
|
||||
{
|
||||
key1: {message: 'key1 message'},
|
||||
key2: {message: 'key2 message'},
|
||||
|
@ -104,14 +106,14 @@ describe('writeCodeTranslations', () => {
|
|||
});
|
||||
|
||||
it('appends missing translations', async () => {
|
||||
const {siteDir, readFile} = await createTmpTranslationFile({
|
||||
const {localizationDir, readFile} = await createTmpTranslationFile({
|
||||
key1: {message: 'key1 message'},
|
||||
key2: {message: 'key2 message'},
|
||||
key3: {message: 'key3 message'},
|
||||
});
|
||||
|
||||
await writeCodeTranslations(
|
||||
{siteDir, locale: 'en'},
|
||||
{localizationDir},
|
||||
{
|
||||
key1: {message: 'key1 message new'},
|
||||
key2: {message: 'key2 message new'},
|
||||
|
@ -133,12 +135,12 @@ describe('writeCodeTranslations', () => {
|
|||
});
|
||||
|
||||
it('appends missing.* translations with prefix', async () => {
|
||||
const {siteDir, readFile} = await createTmpTranslationFile({
|
||||
const {localizationDir, readFile} = await createTmpTranslationFile({
|
||||
key1: {message: 'key1 message'},
|
||||
});
|
||||
|
||||
await writeCodeTranslations(
|
||||
{siteDir, locale: 'en'},
|
||||
{localizationDir},
|
||||
{
|
||||
key1: {message: 'key1 message new'},
|
||||
key2: {message: 'key2 message new'},
|
||||
|
@ -158,12 +160,12 @@ describe('writeCodeTranslations', () => {
|
|||
});
|
||||
|
||||
it('overrides missing translations', async () => {
|
||||
const {siteDir, readFile} = await createTmpTranslationFile({
|
||||
const {localizationDir, readFile} = await createTmpTranslationFile({
|
||||
key1: {message: 'key1 message'},
|
||||
});
|
||||
|
||||
await writeCodeTranslations(
|
||||
{siteDir, locale: 'en'},
|
||||
{localizationDir},
|
||||
{
|
||||
key1: {message: 'key1 message new'},
|
||||
key2: {message: 'key2 message new'},
|
||||
|
@ -183,12 +185,12 @@ describe('writeCodeTranslations', () => {
|
|||
});
|
||||
|
||||
it('overrides missing translations with prefix', async () => {
|
||||
const {siteDir, readFile} = await createTmpTranslationFile({
|
||||
const {localizationDir, readFile} = await createTmpTranslationFile({
|
||||
key1: {message: 'key1 message'},
|
||||
});
|
||||
|
||||
await writeCodeTranslations(
|
||||
{siteDir, locale: 'en'},
|
||||
{localizationDir},
|
||||
{
|
||||
key1: {message: 'key1 message new'},
|
||||
key2: {message: 'key2 message new'},
|
||||
|
@ -209,14 +211,14 @@ describe('writeCodeTranslations', () => {
|
|||
});
|
||||
|
||||
it('always overrides message description', async () => {
|
||||
const {siteDir, readFile} = await createTmpTranslationFile({
|
||||
const {localizationDir, readFile} = await createTmpTranslationFile({
|
||||
key1: {message: 'key1 message', description: 'key1 desc'},
|
||||
key2: {message: 'key2 message', description: 'key2 desc'},
|
||||
key3: {message: 'key3 message', description: undefined},
|
||||
});
|
||||
|
||||
await writeCodeTranslations(
|
||||
{siteDir, locale: 'en'},
|
||||
{localizationDir},
|
||||
{
|
||||
key1: {message: 'key1 message new', description: undefined},
|
||||
key2: {message: 'key2 message new', description: 'key2 desc new'},
|
||||
|
@ -236,9 +238,9 @@ describe('writeCodeTranslations', () => {
|
|||
});
|
||||
|
||||
it('does not create empty translation files', async () => {
|
||||
const {siteDir, readFile} = await createTmpTranslationFile(null);
|
||||
const {localizationDir, readFile} = await createTmpTranslationFile(null);
|
||||
|
||||
await writeCodeTranslations({siteDir, locale: 'en'}, {}, {});
|
||||
await writeCodeTranslations({localizationDir}, {}, {});
|
||||
|
||||
await expect(readFile()).rejects.toThrowError(
|
||||
/ENOENT: no such file or directory, open /,
|
||||
|
@ -247,14 +249,14 @@ describe('writeCodeTranslations', () => {
|
|||
});
|
||||
|
||||
it('throws for invalid content', async () => {
|
||||
const {siteDir} = await createTmpTranslationFile(
|
||||
const {localizationDir} = await createTmpTranslationFile(
|
||||
// @ts-expect-error: bad content on purpose
|
||||
{bad: 'content'},
|
||||
);
|
||||
|
||||
await expect(() =>
|
||||
writeCodeTranslations(
|
||||
{siteDir, locale: 'en'},
|
||||
{localizationDir},
|
||||
{
|
||||
key1: {message: 'key1 message'},
|
||||
},
|
||||
|
@ -269,19 +271,16 @@ describe('writeCodeTranslations', () => {
|
|||
|
||||
describe('writePluginTranslations', () => {
|
||||
it('writes plugin translations', async () => {
|
||||
const siteDir = await createTmpSiteDir();
|
||||
const localizationDir = await createTmpSiteDir();
|
||||
|
||||
const filePath = path.join(
|
||||
siteDir,
|
||||
'i18n',
|
||||
'fr',
|
||||
localizationDir,
|
||||
'my-plugin-name',
|
||||
'my/translation/file.json',
|
||||
);
|
||||
|
||||
await writePluginTranslations({
|
||||
siteDir,
|
||||
locale: 'fr',
|
||||
localizationDir,
|
||||
translationFile: {
|
||||
path: 'my/translation/file',
|
||||
content: {
|
||||
|
@ -306,12 +305,10 @@ describe('writePluginTranslations', () => {
|
|||
});
|
||||
|
||||
it('writes plugin translations consecutively with different options', async () => {
|
||||
const siteDir = await createTmpSiteDir();
|
||||
const localizationDir = await createTmpSiteDir();
|
||||
|
||||
const filePath = path.join(
|
||||
siteDir,
|
||||
'i18n',
|
||||
'fr',
|
||||
localizationDir,
|
||||
'my-plugin-name-my-plugin-id',
|
||||
'my/translation/file.json',
|
||||
);
|
||||
|
@ -321,7 +318,7 @@ describe('writePluginTranslations', () => {
|
|||
options?: WriteTranslationsOptions,
|
||||
) {
|
||||
return writePluginTranslations({
|
||||
siteDir,
|
||||
localizationDir,
|
||||
locale: 'fr',
|
||||
translationFile: {
|
||||
path: 'my/translation/file',
|
||||
|
@ -381,12 +378,11 @@ describe('writePluginTranslations', () => {
|
|||
});
|
||||
|
||||
it('throws with explicit extension', async () => {
|
||||
const siteDir = await createTmpSiteDir();
|
||||
const localizationDir = await createTmpSiteDir();
|
||||
|
||||
await expect(() =>
|
||||
writePluginTranslations({
|
||||
siteDir,
|
||||
locale: 'fr',
|
||||
localizationDir,
|
||||
translationFile: {
|
||||
path: 'my/translation/file.json',
|
||||
content: {},
|
||||
|
@ -409,7 +405,7 @@ describe('writePluginTranslations', () => {
|
|||
|
||||
describe('localizePluginTranslationFile', () => {
|
||||
it('does not localize if localized file does not exist', async () => {
|
||||
const siteDir = await createTmpSiteDir();
|
||||
const localizationDir = await createTmpSiteDir();
|
||||
|
||||
const translationFile: TranslationFile = {
|
||||
path: 'my/translation/file',
|
||||
|
@ -421,8 +417,7 @@ describe('localizePluginTranslationFile', () => {
|
|||
};
|
||||
|
||||
const localizedTranslationFile = await localizePluginTranslationFile({
|
||||
siteDir,
|
||||
locale: 'fr',
|
||||
localizationDir,
|
||||
translationFile,
|
||||
plugin: {
|
||||
name: 'my-plugin-name',
|
||||
|
@ -434,16 +429,10 @@ describe('localizePluginTranslationFile', () => {
|
|||
});
|
||||
|
||||
it('normalizes partially localized translation files', async () => {
|
||||
const siteDir = await createTmpSiteDir();
|
||||
const localizationDir = await createTmpSiteDir();
|
||||
|
||||
await fs.outputJSON(
|
||||
path.join(
|
||||
siteDir,
|
||||
'i18n',
|
||||
'fr',
|
||||
'my-plugin-name',
|
||||
'my/translation/file.json',
|
||||
),
|
||||
path.join(localizationDir, 'my-plugin-name', 'my/translation/file.json'),
|
||||
{
|
||||
key2: {message: 'key2 message localized'},
|
||||
key4: {message: 'key4 message localized'},
|
||||
|
@ -460,8 +449,7 @@ describe('localizePluginTranslationFile', () => {
|
|||
};
|
||||
|
||||
const localizedTranslationFile = await localizePluginTranslationFile({
|
||||
siteDir,
|
||||
locale: 'fr',
|
||||
localizationDir,
|
||||
translationFile,
|
||||
plugin: {
|
||||
name: 'my-plugin-name',
|
||||
|
@ -486,13 +474,13 @@ describe('localizePluginTranslationFile', () => {
|
|||
|
||||
describe('readCodeTranslationFileContent', () => {
|
||||
async function testReadTranslation(val: TranslationFileContent) {
|
||||
const {siteDir} = await createTmpTranslationFile(val);
|
||||
return readCodeTranslationFileContent({siteDir, locale: 'en'});
|
||||
const {localizationDir} = await createTmpTranslationFile(val);
|
||||
return readCodeTranslationFileContent({localizationDir});
|
||||
}
|
||||
|
||||
it("returns undefined if file does't exist", async () => {
|
||||
await expect(
|
||||
readCodeTranslationFileContent({siteDir: 'foo', locale: 'en'}),
|
||||
readCodeTranslationFileContent({localizationDir: 'foo'}),
|
||||
).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import logger from '@docusaurus/logger';
|
|||
import {
|
||||
getPluginI18nPath,
|
||||
toMessageRelativeFilePath,
|
||||
I18N_DIR_NAME,
|
||||
CODE_TRANSLATIONS_FILE_NAME,
|
||||
} from '@docusaurus/utils';
|
||||
import {Joi} from '@docusaurus/utils-validation';
|
||||
|
@ -29,8 +28,7 @@ export type WriteTranslationsOptions = {
|
|||
};
|
||||
|
||||
type TranslationContext = {
|
||||
siteDir: string;
|
||||
locale: string;
|
||||
localizationDir: string;
|
||||
};
|
||||
|
||||
const TranslationFileContentSchema = Joi.object<TranslationFileContent>()
|
||||
|
@ -143,18 +141,8 @@ Maybe you should remove them? ${unknownKeys}`;
|
|||
}
|
||||
}
|
||||
|
||||
// Should we make this configurable?
|
||||
export function getTranslationsLocaleDirPath(
|
||||
context: TranslationContext,
|
||||
): string {
|
||||
return path.join(context.siteDir, I18N_DIR_NAME, context.locale);
|
||||
}
|
||||
|
||||
function getCodeTranslationsFilePath(context: TranslationContext): string {
|
||||
return path.join(
|
||||
getTranslationsLocaleDirPath(context),
|
||||
CODE_TRANSLATIONS_FILE_NAME,
|
||||
);
|
||||
return path.join(context.localizationDir, CODE_TRANSLATIONS_FILE_NAME);
|
||||
}
|
||||
|
||||
export async function readCodeTranslationFileContent(
|
||||
|
@ -187,17 +175,15 @@ function addTranslationFileExtension(translationFilePath: string) {
|
|||
}
|
||||
|
||||
function getPluginTranslationFilePath({
|
||||
siteDir,
|
||||
localizationDir,
|
||||
plugin,
|
||||
locale,
|
||||
translationFilePath,
|
||||
}: TranslationContext & {
|
||||
plugin: InitializedPlugin;
|
||||
translationFilePath: string;
|
||||
}): string {
|
||||
const dirPath = getPluginI18nPath({
|
||||
siteDir,
|
||||
locale,
|
||||
localizationDir,
|
||||
pluginName: plugin.name,
|
||||
pluginId: plugin.options.id,
|
||||
});
|
||||
|
@ -206,9 +192,8 @@ function getPluginTranslationFilePath({
|
|||
}
|
||||
|
||||
export async function writePluginTranslations({
|
||||
siteDir,
|
||||
localizationDir,
|
||||
plugin,
|
||||
locale,
|
||||
translationFile,
|
||||
options,
|
||||
}: TranslationContext & {
|
||||
|
@ -218,8 +203,7 @@ export async function writePluginTranslations({
|
|||
}): Promise<void> {
|
||||
const filePath = getPluginTranslationFilePath({
|
||||
plugin,
|
||||
siteDir,
|
||||
locale,
|
||||
localizationDir,
|
||||
translationFilePath: translationFile.path,
|
||||
});
|
||||
await writeTranslationFileContent({
|
||||
|
@ -230,9 +214,8 @@ export async function writePluginTranslations({
|
|||
}
|
||||
|
||||
export async function localizePluginTranslationFile({
|
||||
siteDir,
|
||||
localizationDir,
|
||||
plugin,
|
||||
locale,
|
||||
translationFile,
|
||||
}: TranslationContext & {
|
||||
plugin: InitializedPlugin;
|
||||
|
@ -240,8 +223,7 @@ export async function localizePluginTranslationFile({
|
|||
}): Promise<TranslationFile> {
|
||||
const filePath = getPluginTranslationFilePath({
|
||||
plugin,
|
||||
siteDir,
|
||||
locale,
|
||||
localizationDir,
|
||||
translationFilePath: translationFile.path,
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue