From 9fb2fc97365a74f8d606cc3b24979c99b75c5298 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Wed, 25 May 2022 11:48:43 +0800 Subject: [PATCH 1/4] feat(core): allow customizing the i18n directory name --- .../src/__tests__/index.test.ts | 3 + .../src/index.ts | 4 +- .../src/__tests__/cli.test.ts | Bin 11753 -> 11809 bytes .../docusaurus-plugin-content-docs/src/cli.ts | 9 +- .../src/versions/__tests__/index.test.ts | 4 + .../src/versions/files.ts | 12 +-- .../src/versions/index.ts | 3 +- .../__snapshots__/index.test.ts.snap | 14 +-- .../src/__tests__/index.test.ts | 10 +-- .../src/index.ts | 10 +-- packages/docusaurus-types/src/index.d.ts | 10 +++ .../src/__tests__/i18nUtils.test.ts | 21 +++-- packages/docusaurus-utils/src/constants.ts | 2 +- packages/docusaurus-utils/src/i18nUtils.ts | 14 +-- packages/docusaurus-utils/src/index.ts | 2 +- packages/docusaurus/src/commands/start.ts | 12 +-- .../src/commands/writeTranslations.ts | 14 ++- .../__snapshots__/config.test.ts.snap | 4 + .../src/server/__tests__/i18n.test.ts | 1 + .../docusaurus/src/server/configValidation.ts | 3 + packages/docusaurus/src/server/i18n.ts | 1 + packages/docusaurus/src/server/index.ts | 11 ++- .../docusaurus/src/server/plugins/index.ts | 3 +- .../__tests__/translations.test.ts | 80 ++++++++---------- .../src/server/translations/translations.ts | 34 ++------ 25 files changed, 124 insertions(+), 157 deletions(-) diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts index 47d4b98fd4e0..e0440f26688c 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts @@ -47,6 +47,7 @@ function getI18n(locale: string): I18n { currentLocale: locale, locales: [locale], defaultLocale: locale, + path: 'i18n', localeConfigs: { [locale]: { calendar: 'gregory', @@ -70,6 +71,7 @@ const getPlugin = async ( i18n: I18n = DefaultI18N, ) => { const generatedFilesDir: string = path.resolve(siteDir, '.docusaurus'); + const i18nDir = path.join(siteDir, i18n.path, i18n.currentLocale); const siteConfig = { title: 'Hello', baseUrl: '/', @@ -81,6 +83,7 @@ const getPlugin = async ( siteConfig, generatedFilesDir, i18n, + i18nDir, } as LoadContext, validateOptions({ validate: normalizePluginOptions as Validate< diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index 2b0355a0f3f1..725451b2804b 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -59,6 +59,7 @@ export default async function pluginContentBlog( siteDir, siteConfig, generatedFilesDir, + i18nDir, i18n: {currentLocale}, } = context; const {onBrokenMarkdownLinks, baseUrl} = siteConfig; @@ -66,8 +67,7 @@ export default async function pluginContentBlog( const contentPaths: BlogContentPaths = { contentPath: path.resolve(siteDir, options.path), contentPathLocalized: getPluginI18nPath({ - siteDir, - locale: currentLocale, + i18nDir, pluginName: 'docusaurus-plugin-content-blog', pluginId: options.id, }), diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/cli.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/cli.test.ts index 194ce3c4e46e20344c3dc2a7f279d59ada8235f0..d9ed52eea89de0a0ffb13abdf585b658b50cde24 100644 GIT binary patch delta 102 zcmaDEy)b4&y9mFILP26lhLwVPrlCcidhKKb{?N^LMLbz}kR>MjDTZ&Zmb}W2BD&d6 av4R6d1gLJ=_ { + // TODO duplicated logic from core; we need to support customization per- + // locale in the future + const i18nDir = path.resolve(siteDir, i18n.path, locale); // Copy docs files. const docsDir = locale === i18n.defaultLocale ? path.resolve(siteDir, docsPath) : getDocsDirPathLocalized({ - siteDir, - locale, + i18nDir, pluginId, versionName: CURRENT_VERSION_NAME, }); @@ -114,8 +116,7 @@ export async function cliDocsVersionCommand( locale === i18n.defaultLocale ? getVersionDocsDirPath(siteDir, pluginId, version) : getDocsDirPathLocalized({ - siteDir, - locale, + i18nDir, pluginId, versionName: version, }); diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts index 15bb3d06d720..2a44137f0153 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts @@ -17,6 +17,7 @@ import type { } from '@docusaurus/plugin-content-docs'; const DefaultI18N: I18n = { + path: 'i18n', currentLocale: 'en', locales: ['en'], defaultLocale: 'en', @@ -37,6 +38,7 @@ describe('readVersionsMetadata', () => { siteDir: simpleSiteDir, baseUrl: '/', i18n: DefaultI18N, + i18nDir: path.join(simpleSiteDir, 'i18n/en'), } as LoadContext; const vCurrent: VersionMetadata = { @@ -198,6 +200,7 @@ describe('readVersionsMetadata', () => { siteDir: versionedSiteDir, baseUrl: '/', i18n: DefaultI18N, + i18nDir: path.join(versionedSiteDir, 'i18n/en'), } as LoadContext; const vCurrent: VersionMetadata = { @@ -636,6 +639,7 @@ describe('readVersionsMetadata', () => { siteDir: versionedSiteDir, baseUrl: '/', i18n: DefaultI18N, + i18nDir: path.join(versionedSiteDir, 'i18n/en'), } as LoadContext; const vCurrent: VersionMetadata = { diff --git a/packages/docusaurus-plugin-content-docs/src/versions/files.ts b/packages/docusaurus-plugin-content-docs/src/versions/files.ts index 04c97efaebaa..b7a95975d8d6 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/files.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/files.ts @@ -55,19 +55,16 @@ export function getVersionSidebarsPath( } export function getDocsDirPathLocalized({ - siteDir, - locale, + i18nDir, pluginId, versionName, }: { - siteDir: string; - locale: string; + i18nDir: string; pluginId: string; versionName: string; }): string { return getPluginI18nPath({ - siteDir, - locale, + i18nDir, pluginName: 'docusaurus-plugin-content-docs', pluginId, subPaths: [ @@ -175,8 +172,7 @@ export async function getVersionMetadataPaths({ > { const isCurrent = versionName === CURRENT_VERSION_NAME; const contentPathLocalized = getDocsDirPathLocalized({ - siteDir: context.siteDir, - locale: context.i18n.currentLocale, + i18nDir: context.i18nDir, pluginId: options.id, versionName, }); diff --git a/packages/docusaurus-plugin-content-docs/src/versions/index.ts b/packages/docusaurus-plugin-content-docs/src/versions/index.ts index 369e0fd6efc2..b4634b8d1ab1 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/index.ts @@ -49,8 +49,7 @@ function getVersionEditUrls({ const editDirPath = options.editCurrentVersion ? options.path : contentPath; const editDirPathLocalized = options.editCurrentVersion ? getDocsDirPathLocalized({ - siteDir: context.siteDir, - locale: context.i18n.currentLocale, + i18nDir: context.i18nDir, versionName: CURRENT_VERSION_NAME, pluginId: options.id, }) diff --git a/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap index 818f94da35f5..bc0f5cef2947 100644 --- a/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap @@ -55,19 +55,19 @@ exports[`docusaurus-plugin-content-pages loads simple pages 1`] = ` exports[`docusaurus-plugin-content-pages loads simple pages with french translations 1`] = ` [ { - "permalink": "/", + "permalink": "/fr/", "source": "@site/src/pages/index.js", "type": "jsx", }, { - "permalink": "/typescript", + "permalink": "/fr/typescript", "source": "@site/src/pages/typescript.tsx", "type": "jsx", }, { "description": "Markdown index page", "frontMatter": {}, - "permalink": "/hello/", + "permalink": "/fr/hello/", "source": "@site/src/pages/hello/index.md", "title": "Index", "type": "mdx", @@ -78,26 +78,26 @@ exports[`docusaurus-plugin-content-pages loads simple pages with french translat "description": "my mdx page", "title": "mdx page", }, - "permalink": "/hello/mdxPage", + "permalink": "/fr/hello/mdxPage", "source": "@site/src/pages/hello/mdxPage.mdx", "title": "mdx page", "type": "mdx", }, { - "permalink": "/hello/translatedJs", + "permalink": "/fr/hello/translatedJs", "source": "@site/i18n/fr/docusaurus-plugin-content-pages/hello/translatedJs.js", "type": "jsx", }, { "description": "translated markdown page (fr)", "frontMatter": {}, - "permalink": "/hello/translatedMd", + "permalink": "/fr/hello/translatedMd", "source": "@site/i18n/fr/docusaurus-plugin-content-pages/hello/translatedMd.md", "title": undefined, "type": "mdx", }, { - "permalink": "/hello/world", + "permalink": "/fr/hello/world", "source": "@site/src/pages/hello/world.js", "type": "jsx", }, diff --git a/packages/docusaurus-plugin-content-pages/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-pages/src/__tests__/index.test.ts index 31706d3a4cd4..dd570260a417 100644 --- a/packages/docusaurus-plugin-content-pages/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-pages/src/__tests__/index.test.ts @@ -32,15 +32,9 @@ describe('docusaurus-plugin-content-pages', () => { it('loads simple pages with french translations', async () => { const siteDir = path.join(__dirname, '__fixtures__', 'website'); - const context = await loadContext({siteDir}); + const context = await loadContext({siteDir, locale: 'fr'}); const plugin = pluginContentPages( - { - ...context, - i18n: { - ...context.i18n, - currentLocale: 'fr', - }, - }, + context, validateOptions({ validate: normalizePluginOptions, options: { diff --git a/packages/docusaurus-plugin-content-pages/src/index.ts b/packages/docusaurus-plugin-content-pages/src/index.ts index a9051e4545e6..97d0fa8a3e68 100644 --- a/packages/docusaurus-plugin-content-pages/src/index.ts +++ b/packages/docusaurus-plugin-content-pages/src/index.ts @@ -48,18 +48,12 @@ export default function pluginContentPages( [admonitions, options.admonitions], ]); } - const { - siteConfig, - siteDir, - generatedFilesDir, - i18n: {currentLocale}, - } = context; + const {siteConfig, siteDir, generatedFilesDir, i18nDir} = context; const contentPaths: PagesContentPaths = { contentPath: path.resolve(siteDir, options.path), contentPathLocalized: getPluginI18nPath({ - siteDir, - locale: currentLocale, + i18nDir, pluginName: 'docusaurus-plugin-content-pages', pluginId: options.id, }), diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index ee4151930eee..2e47cca91a4c 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -70,6 +70,11 @@ export type I18nConfig = { * 3. Will be used for the `` tag */ defaultLocale: string; + /** + * Root folder which all locale folders are relative to. Can be absolute or + * relative to the config file. e.g. `i18n` + */ + path: string; /** List of locales deployed on your site. Must contain `defaultLocale`. */ locales: [string, ...string[]]; /** Individual options for each locale. */ @@ -416,6 +421,11 @@ export type LoadContext = { siteConfig: DocusaurusConfig; siteConfigPath: string; outDir: string; + /** + * Directory where all source translations for the current locale can be found + * in. Constructed with `i18n.path` + `i18n.currentLocale.path` (e.g. i18n/en) + */ + i18nDir: string; /** * Duplicated from `siteConfig.baseUrl`, but probably worth keeping. We mutate * `siteConfig` to make `baseUrl` there localized as well, but that's mostly diff --git a/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts b/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts index c0a458d3a8ec..93178e07d62c 100644 --- a/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts @@ -65,34 +65,33 @@ describe('getPluginI18nPath', () => { it('gets correct path', () => { expect( getPluginI18nPath({ - siteDir: __dirname, - locale: 'zh-Hans', + i18nDir: '/i18n/zh-Hans', pluginName: 'plugin-content-docs', pluginId: 'community', subPaths: ['foo'], }), ).toMatchInlineSnapshot( - `"/packages/docusaurus-utils/src/__tests__/i18n/zh-Hans/plugin-content-docs-community/foo"`, + `"/i18n/zh-Hans/plugin-content-docs-community/foo"`, ); }); it('gets correct path for default plugin', () => { expect( getPluginI18nPath({ - siteDir: __dirname, - locale: 'zh-Hans', + i18nDir: '/i18n/zh-Hans', pluginName: 'plugin-content-docs', subPaths: ['foo'], - }).replace(__dirname, ''), - ).toMatchInlineSnapshot(`"/i18n/zh-Hans/plugin-content-docs/foo"`); + }), + ).toMatchInlineSnapshot( + `"/i18n/zh-Hans/plugin-content-docs/foo"`, + ); }); it('gets correct path when no sub-paths', () => { expect( getPluginI18nPath({ - siteDir: __dirname, - locale: 'zh-Hans', + i18nDir: '/i18n/zh-Hans', pluginName: 'plugin-content-docs', - }).replace(__dirname, ''), - ).toMatchInlineSnapshot(`"/i18n/zh-Hans/plugin-content-docs"`); + }), + ).toMatchInlineSnapshot(`"/i18n/zh-Hans/plugin-content-docs"`); }); }); diff --git a/packages/docusaurus-utils/src/constants.ts b/packages/docusaurus-utils/src/constants.ts index be9405eab9bd..4fc98c8649d6 100644 --- a/packages/docusaurus-utils/src/constants.ts +++ b/packages/docusaurus-utils/src/constants.ts @@ -72,7 +72,7 @@ export const THEME_PATH = `${SRC_DIR_NAME}/theme`; * All translation-related data live here, relative to site directory. Content * will be namespaced by locale. */ -export const I18N_DIR_NAME = 'i18n'; +export const DEFAULT_I18N_DIR_NAME = 'i18n'; /** * Translations for React code. diff --git a/packages/docusaurus-utils/src/i18nUtils.ts b/packages/docusaurus-utils/src/i18nUtils.ts index a6d08cf83749..cf2ea710b62f 100644 --- a/packages/docusaurus-utils/src/i18nUtils.ts +++ b/packages/docusaurus-utils/src/i18nUtils.ts @@ -7,7 +7,7 @@ import path from 'path'; import _ from 'lodash'; -import {DEFAULT_PLUGIN_ID, I18N_DIR_NAME} from './constants'; +import {DEFAULT_PLUGIN_ID} from './constants'; import {normalizeUrl} from './urlUtils'; import type { TranslationFileContent, @@ -46,24 +46,18 @@ export function updateTranslationFileMessages( * expect everything it needs for translations to be found under this path. */ export function getPluginI18nPath({ - siteDir, - locale, + i18nDir, pluginName, pluginId = DEFAULT_PLUGIN_ID, subPaths = [], }: { - siteDir: string; - locale: string; + i18nDir: string; pluginName: string; pluginId?: string | undefined; subPaths?: string[]; }): string { return path.join( - siteDir, - I18N_DIR_NAME, - // Namespace first by locale: convenient to work in a single folder for a - // translator - locale, + i18nDir, // Make it convenient to use for single-instance // ie: return "docs", not "docs-default" nor "docs/default" `${pluginName}${pluginId === DEFAULT_PLUGIN_ID ? '' : `-${pluginId}`}`, diff --git a/packages/docusaurus-utils/src/index.ts b/packages/docusaurus-utils/src/index.ts index fb2c66435ea2..c021dbdda17c 100644 --- a/packages/docusaurus-utils/src/index.ts +++ b/packages/docusaurus-utils/src/index.ts @@ -17,7 +17,7 @@ export { DEFAULT_STATIC_DIR_NAME, OUTPUT_STATIC_ASSETS_DIR_NAME, THEME_PATH, - I18N_DIR_NAME, + DEFAULT_I18N_DIR_NAME, CODE_TRANSLATIONS_FILE_NAME, DEFAULT_PORT, DEFAULT_PLUGIN_ID, diff --git a/packages/docusaurus/src/commands/start.ts b/packages/docusaurus/src/commands/start.ts index a0cae8416493..7c060b2a8f05 100644 --- a/packages/docusaurus/src/commands/start.ts +++ b/packages/docusaurus/src/commands/start.ts @@ -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 & { @@ -82,7 +81,7 @@ export async function start( logger.error(err.stack); }); }, 500); - const {siteConfig, plugins} = props; + const {siteConfig, plugins, i18nDir} = 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, i18nDir]; const pollingOptions = { usePolling: !!cliOptions.poll, diff --git a/packages/docusaurus/src/commands/writeTranslations.ts b/packages/docusaurus/src/commands/writeTranslations.ts index 14ae1e64adc6..91bb229fe425 100644 --- a/packages/docusaurus/src/commands/writeTranslations.ts +++ b/packages/docusaurus/src/commands/writeTranslations.ts @@ -47,14 +47,12 @@ async function getExtraSourceCodeFilePaths(): Promise { } async function writePluginTranslationFiles({ - siteDir, + i18nDir, plugin, - locale, options, }: { - siteDir: string; + i18nDir: 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, + i18nDir, plugin, translationFile, - locale, options, }); }), @@ -86,6 +83,7 @@ export async function writeTranslations( config: options.config, locale: options.locale, }); + const {i18nDir} = 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({i18nDir}, codeTranslations, options); await Promise.all( plugins.map(async (plugin) => { - await writePluginTranslationFiles({siteDir, plugin, locale, options}); + await writePluginTranslationFiles({i18nDir, plugin, options}); }), ); } diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap index abaaab349c57..4f90cf5cfd3b 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap @@ -13,6 +13,7 @@ exports[`loadSiteConfig website with valid async config 1`] = ` "locales": [ "en", ], + "path": "i18n", }, "noIndex": false, "onBrokenLinks": "throw", @@ -51,6 +52,7 @@ exports[`loadSiteConfig website with valid async config creator function 1`] = ` "locales": [ "en", ], + "path": "i18n", }, "noIndex": false, "onBrokenLinks": "throw", @@ -89,6 +91,7 @@ exports[`loadSiteConfig website with valid config creator function 1`] = ` "locales": [ "en", ], + "path": "i18n", }, "noIndex": false, "onBrokenLinks": "throw", @@ -130,6 +133,7 @@ exports[`loadSiteConfig website with valid siteConfig 1`] = ` "locales": [ "en", ], + "path": "i18n", }, "noIndex": false, "onBrokenLinks": "throw", diff --git a/packages/docusaurus/src/server/__tests__/i18n.test.ts b/packages/docusaurus/src/server/__tests__/i18n.test.ts index 84e1e83ada2d..8c99d006545c 100644 --- a/packages/docusaurus/src/server/__tests__/i18n.test.ts +++ b/packages/docusaurus/src/server/__tests__/i18n.test.ts @@ -101,6 +101,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', diff --git a/packages/docusaurus/src/server/configValidation.ts b/packages/docusaurus/src/server/configValidation.ts index f5ef6a3cc9a4..dfb8cc371de5 100644 --- a/packages/docusaurus/src/server/configValidation.ts +++ b/packages/docusaurus/src/server/configValidation.ts @@ -8,6 +8,7 @@ import { DEFAULT_CONFIG_FILE_NAME, 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'; @@ -16,6 +17,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: {}, }; @@ -138,6 +140,7 @@ const LocaleConfigSchema = Joi.object({ const I18N_CONFIG_SCHEMA = Joi.object({ 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) diff --git a/packages/docusaurus/src/server/i18n.ts b/packages/docusaurus/src/server/i18n.ts index cd9bbe4990ea..59b7b85a38f1 100644 --- a/packages/docusaurus/src/server/i18n.ts +++ b/packages/docusaurus/src/server/i18n.ts @@ -60,6 +60,7 @@ Note: Docusaurus only support running one locale at a time.`; return { defaultLocale: i18nConfig.defaultLocale, locales, + path: i18nConfig.path, currentLocale, localeConfigs, }; diff --git a/packages/docusaurus/src/server/index.ts b/packages/docusaurus/src/server/index.ts index 4417f0f7f515..11461b7130c4 100644 --- a/packages/docusaurus/src/server/index.ts +++ b/packages/docusaurus/src/server/index.ts @@ -85,11 +85,11 @@ export async function loadContext( const siteConfig: DocusaurusConfig = {...initialSiteConfig, baseUrl}; + // TODO allow customizing i18nDir per-locale + const i18nDir = path.resolve(siteDir, i18n.path, i18n.currentLocale); + const codeTranslationFileContent = - (await readCodeTranslationFileContent({ - siteDir, - locale: i18n.currentLocale, - })) ?? {}; + (await readCodeTranslationFileContent({i18nDir})) ?? {}; // We only need key->message for code translations const codeTranslations = _.mapValues( @@ -100,6 +100,7 @@ export async function loadContext( return { siteDir, generatedFilesDir, + i18nDir, siteConfig, siteConfigPath, outDir, @@ -125,6 +126,7 @@ export async function load(options: LoadContextOptions): Promise { outDir, baseUrl, i18n, + i18nDir, codeTranslations: siteCodeTranslations, } = context; const {plugins, pluginsRouteConfigs, globalData} = await loadPlugins(context); @@ -246,6 +248,7 @@ ${Object.entries(registry) outDir, baseUrl, i18n, + i18nDir, generatedFilesDir, routes: pluginsRouteConfigs, routesPaths, diff --git a/packages/docusaurus/src/server/plugins/index.ts b/packages/docusaurus/src/server/plugins/index.ts index 5a8dbb98d095..06ad5fcef73c 100644 --- a/packages/docusaurus/src/server/plugins/index.ts +++ b/packages/docusaurus/src/server/plugins/index.ts @@ -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, + i18nDir: context.i18nDir, translationFile, plugin, }), diff --git a/packages/docusaurus/src/server/translations/__tests__/translations.test.ts b/packages/docusaurus/src/server/translations/__tests__/translations.test.ts index 70da33ffd3eb..bdcae29c1656 100644 --- a/packages/docusaurus/src/server/translations/__tests__/translations.test.ts +++ b/packages/docusaurus/src/server/translations/__tests__/translations.test.ts @@ -44,7 +44,7 @@ async function createTmpTranslationFile( } return { - siteDir, + i18nDir: path.join(siteDir, 'i18n/en'), readFile() { return fs.readJSON(filePath); }, @@ -60,9 +60,9 @@ describe('writeCodeTranslations', () => { }); it('creates new translation file', async () => { - const {siteDir, readFile} = await createTmpTranslationFile(null); + const {i18nDir, readFile} = await createTmpTranslationFile(null); await writeCodeTranslations( - {siteDir, locale: 'en'}, + {i18nDir}, { key1: {message: 'key1 message'}, key2: {message: 'key2 message'}, @@ -82,9 +82,9 @@ describe('writeCodeTranslations', () => { }); it('creates new translation file with prefix', async () => { - const {siteDir, readFile} = await createTmpTranslationFile(null); + const {i18nDir, readFile} = await createTmpTranslationFile(null); await writeCodeTranslations( - {siteDir, locale: 'en'}, + {i18nDir}, { key1: {message: 'key1 message'}, key2: {message: 'key2 message'}, @@ -106,14 +106,14 @@ describe('writeCodeTranslations', () => { }); it('appends missing translations', async () => { - const {siteDir, readFile} = await createTmpTranslationFile({ + const {i18nDir, readFile} = await createTmpTranslationFile({ key1: {message: 'key1 message'}, key2: {message: 'key2 message'}, key3: {message: 'key3 message'}, }); await writeCodeTranslations( - {siteDir, locale: 'en'}, + {i18nDir}, { key1: {message: 'key1 message new'}, key2: {message: 'key2 message new'}, @@ -135,12 +135,12 @@ describe('writeCodeTranslations', () => { }); it('appends missing.* translations with prefix', async () => { - const {siteDir, readFile} = await createTmpTranslationFile({ + const {i18nDir, readFile} = await createTmpTranslationFile({ key1: {message: 'key1 message'}, }); await writeCodeTranslations( - {siteDir, locale: 'en'}, + {i18nDir}, { key1: {message: 'key1 message new'}, key2: {message: 'key2 message new'}, @@ -160,12 +160,12 @@ describe('writeCodeTranslations', () => { }); it('overrides missing translations', async () => { - const {siteDir, readFile} = await createTmpTranslationFile({ + const {i18nDir, readFile} = await createTmpTranslationFile({ key1: {message: 'key1 message'}, }); await writeCodeTranslations( - {siteDir, locale: 'en'}, + {i18nDir}, { key1: {message: 'key1 message new'}, key2: {message: 'key2 message new'}, @@ -185,12 +185,12 @@ describe('writeCodeTranslations', () => { }); it('overrides missing translations with prefix', async () => { - const {siteDir, readFile} = await createTmpTranslationFile({ + const {i18nDir, readFile} = await createTmpTranslationFile({ key1: {message: 'key1 message'}, }); await writeCodeTranslations( - {siteDir, locale: 'en'}, + {i18nDir}, { key1: {message: 'key1 message new'}, key2: {message: 'key2 message new'}, @@ -211,14 +211,14 @@ describe('writeCodeTranslations', () => { }); it('always overrides message description', async () => { - const {siteDir, readFile} = await createTmpTranslationFile({ + const {i18nDir, 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'}, + {i18nDir}, { key1: {message: 'key1 message new', description: undefined}, key2: {message: 'key2 message new', description: 'key2 desc new'}, @@ -238,9 +238,9 @@ describe('writeCodeTranslations', () => { }); it('does not create empty translation files', async () => { - const {siteDir, readFile} = await createTmpTranslationFile(null); + const {i18nDir, readFile} = await createTmpTranslationFile(null); - await writeCodeTranslations({siteDir, locale: 'en'}, {}, {}); + await writeCodeTranslations({i18nDir}, {}, {}); await expect(readFile()).rejects.toThrowError( /ENOENT: no such file or directory, open /, @@ -249,14 +249,14 @@ describe('writeCodeTranslations', () => { }); it('throws for invalid content', async () => { - const {siteDir} = await createTmpTranslationFile( + const {i18nDir} = await createTmpTranslationFile( // @ts-expect-error: bad content on purpose {bad: 'content'}, ); await expect(() => writeCodeTranslations( - {siteDir, locale: 'en'}, + {i18nDir}, { key1: {message: 'key1 message'}, }, @@ -271,18 +271,16 @@ describe('writeCodeTranslations', () => { describe('writePluginTranslations', () => { it('writes plugin translations', async () => { - const siteDir = await createTmpSiteDir(); + const i18nDir = await createTmpSiteDir(); const filePath = path.join( - siteDir, - 'i18n', - 'fr', + i18nDir, 'my-plugin-name', 'my/translation/file.json', ); await writePluginTranslations({ - siteDir, + i18nDir, locale: 'fr', translationFile: { path: 'my/translation/file', @@ -308,12 +306,10 @@ describe('writePluginTranslations', () => { }); it('writes plugin translations consecutively with different options', async () => { - const siteDir = await createTmpSiteDir(); + const i18nDir = await createTmpSiteDir(); const filePath = path.join( - siteDir, - 'i18n', - 'fr', + i18nDir, 'my-plugin-name-my-plugin-id', 'my/translation/file.json', ); @@ -323,7 +319,7 @@ describe('writePluginTranslations', () => { options?: WriteTranslationsOptions, ) { return writePluginTranslations({ - siteDir, + i18nDir, locale: 'fr', translationFile: { path: 'my/translation/file', @@ -383,11 +379,11 @@ describe('writePluginTranslations', () => { }); it('throws with explicit extension', async () => { - const siteDir = await createTmpSiteDir(); + const i18nDir = await createTmpSiteDir(); await expect(() => writePluginTranslations({ - siteDir, + i18nDir, locale: 'fr', translationFile: { path: 'my/translation/file.json', @@ -411,7 +407,7 @@ describe('writePluginTranslations', () => { describe('localizePluginTranslationFile', () => { it('does not localize if localized file does not exist', async () => { - const siteDir = await createTmpSiteDir(); + const i18nDir = await createTmpSiteDir(); const translationFile: TranslationFile = { path: 'my/translation/file', @@ -423,7 +419,7 @@ describe('localizePluginTranslationFile', () => { }; const localizedTranslationFile = await localizePluginTranslationFile({ - siteDir, + i18nDir, locale: 'fr', translationFile, plugin: { @@ -436,16 +432,10 @@ describe('localizePluginTranslationFile', () => { }); it('normalizes partially localized translation files', async () => { - const siteDir = await createTmpSiteDir(); + const i18nDir = await createTmpSiteDir(); await fs.outputJSON( - path.join( - siteDir, - 'i18n', - 'fr', - 'my-plugin-name', - 'my/translation/file.json', - ), + path.join(i18nDir, 'my-plugin-name', 'my/translation/file.json'), { key2: {message: 'key2 message localized'}, key4: {message: 'key4 message localized'}, @@ -462,7 +452,7 @@ describe('localizePluginTranslationFile', () => { }; const localizedTranslationFile = await localizePluginTranslationFile({ - siteDir, + i18nDir, locale: 'fr', translationFile, plugin: { @@ -488,13 +478,13 @@ describe('localizePluginTranslationFile', () => { describe('readCodeTranslationFileContent', () => { async function testReadTranslation(val: TranslationFileContent) { - const {siteDir} = await createTmpTranslationFile(val); - return readCodeTranslationFileContent({siteDir, locale: 'en'}); + const {i18nDir} = await createTmpTranslationFile(val); + return readCodeTranslationFileContent({i18nDir}); } it("returns undefined if file does't exist", async () => { await expect( - readCodeTranslationFileContent({siteDir: 'foo', locale: 'en'}), + readCodeTranslationFileContent({i18nDir: 'foo'}), ).resolves.toBeUndefined(); }); diff --git a/packages/docusaurus/src/server/translations/translations.ts b/packages/docusaurus/src/server/translations/translations.ts index fd3fb0305523..7f4368701d34 100644 --- a/packages/docusaurus/src/server/translations/translations.ts +++ b/packages/docusaurus/src/server/translations/translations.ts @@ -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; + i18nDir: string; }; const TranslationFileContentSchema = Joi.object() @@ -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.i18nDir, CODE_TRANSLATIONS_FILE_NAME); } export async function readCodeTranslationFileContent( @@ -187,17 +175,15 @@ function addTranslationFileExtension(translationFilePath: string) { } function getPluginTranslationFilePath({ - siteDir, + i18nDir, plugin, - locale, translationFilePath, }: TranslationContext & { plugin: InitializedPlugin; translationFilePath: string; }): string { const dirPath = getPluginI18nPath({ - siteDir, - locale, + i18nDir, pluginName: plugin.name, pluginId: plugin.options.id, }); @@ -206,9 +192,8 @@ function getPluginTranslationFilePath({ } export async function writePluginTranslations({ - siteDir, + i18nDir, plugin, - locale, translationFile, options, }: TranslationContext & { @@ -218,8 +203,7 @@ export async function writePluginTranslations({ }): Promise { const filePath = getPluginTranslationFilePath({ plugin, - siteDir, - locale, + i18nDir, translationFilePath: translationFile.path, }); await writeTranslationFileContent({ @@ -230,9 +214,8 @@ export async function writePluginTranslations({ } export async function localizePluginTranslationFile({ - siteDir, + i18nDir, plugin, - locale, translationFile, }: TranslationContext & { plugin: InitializedPlugin; @@ -240,8 +223,7 @@ export async function localizePluginTranslationFile({ }): Promise { const filePath = getPluginTranslationFilePath({ plugin, - siteDir, - locale, + i18nDir, translationFilePath: translationFile.path, }); From 3fd1b1b53cae52be436967ac138dcf45f16ed84e Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Fri, 27 May 2022 18:47:50 +0800 Subject: [PATCH 2/4] i18nDir -> localizationDir --- .../src/__tests__/index.test.ts | 4 +- .../src/index.ts | 4 +- .../docusaurus-plugin-content-docs/src/cli.ts | 10 +-- .../src/versions/__tests__/index.test.ts | 6 +- .../src/versions/files.ts | 8 +-- .../src/versions/index.ts | 2 +- .../src/index.ts | 4 +- packages/docusaurus-types/src/index.d.ts | 2 +- .../src/__tests__/i18nUtils.test.ts | 6 +- packages/docusaurus-utils/src/i18nUtils.ts | 6 +- packages/docusaurus/src/commands/start.ts | 4 +- .../src/commands/writeTranslations.ts | 12 ++-- packages/docusaurus/src/server/index.ts | 12 ++-- .../docusaurus/src/server/plugins/index.ts | 2 +- .../__tests__/translations.test.ts | 70 +++++++++---------- .../src/server/translations/translations.ts | 16 ++--- 16 files changed, 84 insertions(+), 84 deletions(-) diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts index e0440f26688c..4ec710ce0a39 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts @@ -71,7 +71,7 @@ const getPlugin = async ( i18n: I18n = DefaultI18N, ) => { const generatedFilesDir: string = path.resolve(siteDir, '.docusaurus'); - const i18nDir = path.join(siteDir, i18n.path, i18n.currentLocale); + const localizationDir = path.join(siteDir, i18n.path, i18n.currentLocale); const siteConfig = { title: 'Hello', baseUrl: '/', @@ -83,7 +83,7 @@ const getPlugin = async ( siteConfig, generatedFilesDir, i18n, - i18nDir, + localizationDir, } as LoadContext, validateOptions({ validate: normalizePluginOptions as Validate< diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index 725451b2804b..f0c1f8cc24ed 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -59,7 +59,7 @@ export default async function pluginContentBlog( siteDir, siteConfig, generatedFilesDir, - i18nDir, + localizationDir, i18n: {currentLocale}, } = context; const {onBrokenMarkdownLinks, baseUrl} = siteConfig; @@ -67,7 +67,7 @@ export default async function pluginContentBlog( const contentPaths: BlogContentPaths = { contentPath: path.resolve(siteDir, options.path), contentPathLocalized: getPluginI18nPath({ - i18nDir, + localizationDir, pluginName: 'docusaurus-plugin-content-blog', pluginId: options.id, }), diff --git a/packages/docusaurus-plugin-content-docs/src/cli.ts b/packages/docusaurus-plugin-content-docs/src/cli.ts index f49798f6e222..1818a3f4e22e 100644 --- a/packages/docusaurus-plugin-content-docs/src/cli.ts +++ b/packages/docusaurus-plugin-content-docs/src/cli.ts @@ -85,15 +85,15 @@ export async function cliDocsVersionCommand( await Promise.all( i18n.locales.map(async (locale) => { - // TODO duplicated logic from core; we need to support customization per- - // locale in the future - const i18nDir = path.resolve(siteDir, i18n.path, locale); + // TODO duplicated logic from core, so duplicate comment as well: we need + // to support customization per-locale in the future + const localizationDir = path.resolve(siteDir, i18n.path, locale); // Copy docs files. const docsDir = locale === i18n.defaultLocale ? path.resolve(siteDir, docsPath) : getDocsDirPathLocalized({ - i18nDir, + localizationDir, pluginId, versionName: CURRENT_VERSION_NAME, }); @@ -116,7 +116,7 @@ export async function cliDocsVersionCommand( locale === i18n.defaultLocale ? getVersionDocsDirPath(siteDir, pluginId, version) : getDocsDirPathLocalized({ - i18nDir, + localizationDir, pluginId, versionName: version, }); diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts index 2a44137f0153..a52ba1b7d186 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts @@ -38,7 +38,7 @@ describe('readVersionsMetadata', () => { siteDir: simpleSiteDir, baseUrl: '/', i18n: DefaultI18N, - i18nDir: path.join(simpleSiteDir, 'i18n/en'), + localizationDir: path.join(simpleSiteDir, 'i18n/en'), } as LoadContext; const vCurrent: VersionMetadata = { @@ -200,7 +200,7 @@ describe('readVersionsMetadata', () => { siteDir: versionedSiteDir, baseUrl: '/', i18n: DefaultI18N, - i18nDir: path.join(versionedSiteDir, 'i18n/en'), + localizationDir: path.join(versionedSiteDir, 'i18n/en'), } as LoadContext; const vCurrent: VersionMetadata = { @@ -639,7 +639,7 @@ describe('readVersionsMetadata', () => { siteDir: versionedSiteDir, baseUrl: '/', i18n: DefaultI18N, - i18nDir: path.join(versionedSiteDir, 'i18n/en'), + localizationDir: path.join(versionedSiteDir, 'i18n/en'), } as LoadContext; const vCurrent: VersionMetadata = { diff --git a/packages/docusaurus-plugin-content-docs/src/versions/files.ts b/packages/docusaurus-plugin-content-docs/src/versions/files.ts index b7a95975d8d6..2f045717c29e 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/files.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/files.ts @@ -55,16 +55,16 @@ export function getVersionSidebarsPath( } export function getDocsDirPathLocalized({ - i18nDir, + localizationDir, pluginId, versionName, }: { - i18nDir: string; + localizationDir: string; pluginId: string; versionName: string; }): string { return getPluginI18nPath({ - i18nDir, + localizationDir, pluginName: 'docusaurus-plugin-content-docs', pluginId, subPaths: [ @@ -172,7 +172,7 @@ export async function getVersionMetadataPaths({ > { const isCurrent = versionName === CURRENT_VERSION_NAME; const contentPathLocalized = getDocsDirPathLocalized({ - i18nDir: context.i18nDir, + localizationDir: context.localizationDir, pluginId: options.id, versionName, }); diff --git a/packages/docusaurus-plugin-content-docs/src/versions/index.ts b/packages/docusaurus-plugin-content-docs/src/versions/index.ts index b4634b8d1ab1..d39bee56198d 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/index.ts @@ -49,7 +49,7 @@ function getVersionEditUrls({ const editDirPath = options.editCurrentVersion ? options.path : contentPath; const editDirPathLocalized = options.editCurrentVersion ? getDocsDirPathLocalized({ - i18nDir: context.i18nDir, + localizationDir: context.localizationDir, versionName: CURRENT_VERSION_NAME, pluginId: options.id, }) diff --git a/packages/docusaurus-plugin-content-pages/src/index.ts b/packages/docusaurus-plugin-content-pages/src/index.ts index 97d0fa8a3e68..7480962d07cc 100644 --- a/packages/docusaurus-plugin-content-pages/src/index.ts +++ b/packages/docusaurus-plugin-content-pages/src/index.ts @@ -48,12 +48,12 @@ export default function pluginContentPages( [admonitions, options.admonitions], ]); } - const {siteConfig, siteDir, generatedFilesDir, i18nDir} = context; + const {siteConfig, siteDir, generatedFilesDir, localizationDir} = context; const contentPaths: PagesContentPaths = { contentPath: path.resolve(siteDir, options.path), contentPathLocalized: getPluginI18nPath({ - i18nDir, + localizationDir, pluginName: 'docusaurus-plugin-content-pages', pluginId: options.id, }), diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index 2e47cca91a4c..f21b77f7a9de 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -425,7 +425,7 @@ export type LoadContext = { * Directory where all source translations for the current locale can be found * in. Constructed with `i18n.path` + `i18n.currentLocale.path` (e.g. i18n/en) */ - i18nDir: string; + localizationDir: string; /** * Duplicated from `siteConfig.baseUrl`, but probably worth keeping. We mutate * `siteConfig` to make `baseUrl` there localized as well, but that's mostly diff --git a/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts b/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts index 93178e07d62c..6e8f4e198a7e 100644 --- a/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts @@ -65,7 +65,7 @@ describe('getPluginI18nPath', () => { it('gets correct path', () => { expect( getPluginI18nPath({ - i18nDir: '/i18n/zh-Hans', + localizationDir: '/i18n/zh-Hans', pluginName: 'plugin-content-docs', pluginId: 'community', subPaths: ['foo'], @@ -77,7 +77,7 @@ describe('getPluginI18nPath', () => { it('gets correct path for default plugin', () => { expect( getPluginI18nPath({ - i18nDir: '/i18n/zh-Hans', + localizationDir: '/i18n/zh-Hans', pluginName: 'plugin-content-docs', subPaths: ['foo'], }), @@ -88,7 +88,7 @@ describe('getPluginI18nPath', () => { it('gets correct path when no sub-paths', () => { expect( getPluginI18nPath({ - i18nDir: '/i18n/zh-Hans', + localizationDir: '/i18n/zh-Hans', pluginName: 'plugin-content-docs', }), ).toMatchInlineSnapshot(`"/i18n/zh-Hans/plugin-content-docs"`); diff --git a/packages/docusaurus-utils/src/i18nUtils.ts b/packages/docusaurus-utils/src/i18nUtils.ts index cf2ea710b62f..8c706f1b8ce7 100644 --- a/packages/docusaurus-utils/src/i18nUtils.ts +++ b/packages/docusaurus-utils/src/i18nUtils.ts @@ -46,18 +46,18 @@ export function updateTranslationFileMessages( * expect everything it needs for translations to be found under this path. */ export function getPluginI18nPath({ - i18nDir, + localizationDir, pluginName, pluginId = DEFAULT_PLUGIN_ID, subPaths = [], }: { - i18nDir: string; + localizationDir: string; pluginName: string; pluginId?: string | undefined; subPaths?: string[]; }): string { return path.join( - i18nDir, + localizationDir, // Make it convenient to use for single-instance // ie: return "docs", not "docs-default" nor "docs/default" `${pluginName}${pluginId === DEFAULT_PLUGIN_ID ? '' : `-${pluginId}`}`, diff --git a/packages/docusaurus/src/commands/start.ts b/packages/docusaurus/src/commands/start.ts index 7c060b2a8f05..b4eb42acf793 100644 --- a/packages/docusaurus/src/commands/start.ts +++ b/packages/docusaurus/src/commands/start.ts @@ -81,7 +81,7 @@ export async function start( logger.error(err.stack); }); }, 500); - const {siteConfig, plugins, i18nDir} = props; + const {siteConfig, plugins, localizationDir} = props; const normalizeToSiteDir = (filepath: string) => { if (filepath && path.isAbsolute(filepath)) { @@ -95,7 +95,7 @@ export async function start( .filter(Boolean) .map(normalizeToSiteDir); - const pathsToWatch = [...pluginPaths, props.siteConfigPath, i18nDir]; + const pathsToWatch = [...pluginPaths, props.siteConfigPath, localizationDir]; const pollingOptions = { usePolling: !!cliOptions.poll, diff --git a/packages/docusaurus/src/commands/writeTranslations.ts b/packages/docusaurus/src/commands/writeTranslations.ts index 91bb229fe425..d69014306fcf 100644 --- a/packages/docusaurus/src/commands/writeTranslations.ts +++ b/packages/docusaurus/src/commands/writeTranslations.ts @@ -47,11 +47,11 @@ async function getExtraSourceCodeFilePaths(): Promise { } async function writePluginTranslationFiles({ - i18nDir, + localizationDir, plugin, options, }: { - i18nDir: string; + localizationDir: string; plugin: InitializedPlugin; options: WriteTranslationsOptions; }) { @@ -64,7 +64,7 @@ async function writePluginTranslationFiles({ await Promise.all( translationFiles.map(async (translationFile) => { await writePluginTranslations({ - i18nDir, + localizationDir, plugin, translationFile, options, @@ -83,7 +83,7 @@ export async function writeTranslations( config: options.config, locale: options.locale, }); - const {i18nDir} = context; + const {localizationDir} = context; const plugins = await initPlugins(context); const locale = options.locale ?? context.i18n.defaultLocale; @@ -114,11 +114,11 @@ Available locales are: ${context.i18n.locales.join(',')}.`, defaultCodeMessages, }); - await writeCodeTranslations({i18nDir}, codeTranslations, options); + await writeCodeTranslations({localizationDir}, codeTranslations, options); await Promise.all( plugins.map(async (plugin) => { - await writePluginTranslationFiles({i18nDir, plugin, options}); + await writePluginTranslationFiles({localizationDir, plugin, options}); }), ); } diff --git a/packages/docusaurus/src/server/index.ts b/packages/docusaurus/src/server/index.ts index 11461b7130c4..b470b38ef145 100644 --- a/packages/docusaurus/src/server/index.ts +++ b/packages/docusaurus/src/server/index.ts @@ -85,11 +85,11 @@ export async function loadContext( const siteConfig: DocusaurusConfig = {...initialSiteConfig, baseUrl}; - // TODO allow customizing i18nDir per-locale - const i18nDir = path.resolve(siteDir, i18n.path, i18n.currentLocale); + // TODO allow customizing localizationDir per-locale + const localizationDir = path.resolve(siteDir, i18n.path, i18n.currentLocale); const codeTranslationFileContent = - (await readCodeTranslationFileContent({i18nDir})) ?? {}; + (await readCodeTranslationFileContent({localizationDir})) ?? {}; // We only need key->message for code translations const codeTranslations = _.mapValues( @@ -100,7 +100,7 @@ export async function loadContext( return { siteDir, generatedFilesDir, - i18nDir, + localizationDir, siteConfig, siteConfigPath, outDir, @@ -126,7 +126,7 @@ export async function load(options: LoadContextOptions): Promise { outDir, baseUrl, i18n, - i18nDir, + localizationDir, codeTranslations: siteCodeTranslations, } = context; const {plugins, pluginsRouteConfigs, globalData} = await loadPlugins(context); @@ -248,7 +248,7 @@ ${Object.entries(registry) outDir, baseUrl, i18n, - i18nDir, + localizationDir, generatedFilesDir, routes: pluginsRouteConfigs, routesPaths, diff --git a/packages/docusaurus/src/server/plugins/index.ts b/packages/docusaurus/src/server/plugins/index.ts index 06ad5fcef73c..73fba212b289 100644 --- a/packages/docusaurus/src/server/plugins/index.ts +++ b/packages/docusaurus/src/server/plugins/index.ts @@ -56,7 +56,7 @@ export async function loadPlugins(context: LoadContext): Promise<{ const translationFiles = await Promise.all( rawTranslationFiles.map((translationFile) => localizePluginTranslationFile({ - i18nDir: context.i18nDir, + localizationDir: context.localizationDir, translationFile, plugin, }), diff --git a/packages/docusaurus/src/server/translations/__tests__/translations.test.ts b/packages/docusaurus/src/server/translations/__tests__/translations.test.ts index bdcae29c1656..7d2ce1cb2811 100644 --- a/packages/docusaurus/src/server/translations/__tests__/translations.test.ts +++ b/packages/docusaurus/src/server/translations/__tests__/translations.test.ts @@ -44,7 +44,7 @@ async function createTmpTranslationFile( } return { - i18nDir: path.join(siteDir, 'i18n/en'), + localizationDir: path.join(siteDir, 'i18n/en'), readFile() { return fs.readJSON(filePath); }, @@ -60,9 +60,9 @@ describe('writeCodeTranslations', () => { }); it('creates new translation file', async () => { - const {i18nDir, readFile} = await createTmpTranslationFile(null); + const {localizationDir, readFile} = await createTmpTranslationFile(null); await writeCodeTranslations( - {i18nDir}, + {localizationDir}, { key1: {message: 'key1 message'}, key2: {message: 'key2 message'}, @@ -82,9 +82,9 @@ describe('writeCodeTranslations', () => { }); it('creates new translation file with prefix', async () => { - const {i18nDir, readFile} = await createTmpTranslationFile(null); + const {localizationDir, readFile} = await createTmpTranslationFile(null); await writeCodeTranslations( - {i18nDir}, + {localizationDir}, { key1: {message: 'key1 message'}, key2: {message: 'key2 message'}, @@ -106,14 +106,14 @@ describe('writeCodeTranslations', () => { }); it('appends missing translations', async () => { - const {i18nDir, readFile} = await createTmpTranslationFile({ + const {localizationDir, readFile} = await createTmpTranslationFile({ key1: {message: 'key1 message'}, key2: {message: 'key2 message'}, key3: {message: 'key3 message'}, }); await writeCodeTranslations( - {i18nDir}, + {localizationDir}, { key1: {message: 'key1 message new'}, key2: {message: 'key2 message new'}, @@ -135,12 +135,12 @@ describe('writeCodeTranslations', () => { }); it('appends missing.* translations with prefix', async () => { - const {i18nDir, readFile} = await createTmpTranslationFile({ + const {localizationDir, readFile} = await createTmpTranslationFile({ key1: {message: 'key1 message'}, }); await writeCodeTranslations( - {i18nDir}, + {localizationDir}, { key1: {message: 'key1 message new'}, key2: {message: 'key2 message new'}, @@ -160,12 +160,12 @@ describe('writeCodeTranslations', () => { }); it('overrides missing translations', async () => { - const {i18nDir, readFile} = await createTmpTranslationFile({ + const {localizationDir, readFile} = await createTmpTranslationFile({ key1: {message: 'key1 message'}, }); await writeCodeTranslations( - {i18nDir}, + {localizationDir}, { key1: {message: 'key1 message new'}, key2: {message: 'key2 message new'}, @@ -185,12 +185,12 @@ describe('writeCodeTranslations', () => { }); it('overrides missing translations with prefix', async () => { - const {i18nDir, readFile} = await createTmpTranslationFile({ + const {localizationDir, readFile} = await createTmpTranslationFile({ key1: {message: 'key1 message'}, }); await writeCodeTranslations( - {i18nDir}, + {localizationDir}, { key1: {message: 'key1 message new'}, key2: {message: 'key2 message new'}, @@ -211,14 +211,14 @@ describe('writeCodeTranslations', () => { }); it('always overrides message description', async () => { - const {i18nDir, 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( - {i18nDir}, + {localizationDir}, { key1: {message: 'key1 message new', description: undefined}, key2: {message: 'key2 message new', description: 'key2 desc new'}, @@ -238,9 +238,9 @@ describe('writeCodeTranslations', () => { }); it('does not create empty translation files', async () => { - const {i18nDir, readFile} = await createTmpTranslationFile(null); + const {localizationDir, readFile} = await createTmpTranslationFile(null); - await writeCodeTranslations({i18nDir}, {}, {}); + await writeCodeTranslations({localizationDir}, {}, {}); await expect(readFile()).rejects.toThrowError( /ENOENT: no such file or directory, open /, @@ -249,14 +249,14 @@ describe('writeCodeTranslations', () => { }); it('throws for invalid content', async () => { - const {i18nDir} = await createTmpTranslationFile( + const {localizationDir} = await createTmpTranslationFile( // @ts-expect-error: bad content on purpose {bad: 'content'}, ); await expect(() => writeCodeTranslations( - {i18nDir}, + {localizationDir}, { key1: {message: 'key1 message'}, }, @@ -271,16 +271,16 @@ describe('writeCodeTranslations', () => { describe('writePluginTranslations', () => { it('writes plugin translations', async () => { - const i18nDir = await createTmpSiteDir(); + const localizationDir = await createTmpSiteDir(); const filePath = path.join( - i18nDir, + localizationDir, 'my-plugin-name', 'my/translation/file.json', ); await writePluginTranslations({ - i18nDir, + localizationDir, locale: 'fr', translationFile: { path: 'my/translation/file', @@ -306,10 +306,10 @@ describe('writePluginTranslations', () => { }); it('writes plugin translations consecutively with different options', async () => { - const i18nDir = await createTmpSiteDir(); + const localizationDir = await createTmpSiteDir(); const filePath = path.join( - i18nDir, + localizationDir, 'my-plugin-name-my-plugin-id', 'my/translation/file.json', ); @@ -319,7 +319,7 @@ describe('writePluginTranslations', () => { options?: WriteTranslationsOptions, ) { return writePluginTranslations({ - i18nDir, + localizationDir, locale: 'fr', translationFile: { path: 'my/translation/file', @@ -379,11 +379,11 @@ describe('writePluginTranslations', () => { }); it('throws with explicit extension', async () => { - const i18nDir = await createTmpSiteDir(); + const localizationDir = await createTmpSiteDir(); await expect(() => writePluginTranslations({ - i18nDir, + localizationDir, locale: 'fr', translationFile: { path: 'my/translation/file.json', @@ -407,7 +407,7 @@ describe('writePluginTranslations', () => { describe('localizePluginTranslationFile', () => { it('does not localize if localized file does not exist', async () => { - const i18nDir = await createTmpSiteDir(); + const localizationDir = await createTmpSiteDir(); const translationFile: TranslationFile = { path: 'my/translation/file', @@ -419,7 +419,7 @@ describe('localizePluginTranslationFile', () => { }; const localizedTranslationFile = await localizePluginTranslationFile({ - i18nDir, + localizationDir, locale: 'fr', translationFile, plugin: { @@ -432,10 +432,10 @@ describe('localizePluginTranslationFile', () => { }); it('normalizes partially localized translation files', async () => { - const i18nDir = await createTmpSiteDir(); + const localizationDir = await createTmpSiteDir(); await fs.outputJSON( - path.join(i18nDir, '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'}, @@ -452,7 +452,7 @@ describe('localizePluginTranslationFile', () => { }; const localizedTranslationFile = await localizePluginTranslationFile({ - i18nDir, + localizationDir, locale: 'fr', translationFile, plugin: { @@ -478,13 +478,13 @@ describe('localizePluginTranslationFile', () => { describe('readCodeTranslationFileContent', () => { async function testReadTranslation(val: TranslationFileContent) { - const {i18nDir} = await createTmpTranslationFile(val); - return readCodeTranslationFileContent({i18nDir}); + const {localizationDir} = await createTmpTranslationFile(val); + return readCodeTranslationFileContent({localizationDir}); } it("returns undefined if file does't exist", async () => { await expect( - readCodeTranslationFileContent({i18nDir: 'foo'}), + readCodeTranslationFileContent({localizationDir: 'foo'}), ).resolves.toBeUndefined(); }); diff --git a/packages/docusaurus/src/server/translations/translations.ts b/packages/docusaurus/src/server/translations/translations.ts index 7f4368701d34..83d19495bffc 100644 --- a/packages/docusaurus/src/server/translations/translations.ts +++ b/packages/docusaurus/src/server/translations/translations.ts @@ -28,7 +28,7 @@ export type WriteTranslationsOptions = { }; type TranslationContext = { - i18nDir: string; + localizationDir: string; }; const TranslationFileContentSchema = Joi.object() @@ -142,7 +142,7 @@ Maybe you should remove them? ${unknownKeys}`; } function getCodeTranslationsFilePath(context: TranslationContext): string { - return path.join(context.i18nDir, CODE_TRANSLATIONS_FILE_NAME); + return path.join(context.localizationDir, CODE_TRANSLATIONS_FILE_NAME); } export async function readCodeTranslationFileContent( @@ -175,7 +175,7 @@ function addTranslationFileExtension(translationFilePath: string) { } function getPluginTranslationFilePath({ - i18nDir, + localizationDir, plugin, translationFilePath, }: TranslationContext & { @@ -183,7 +183,7 @@ function getPluginTranslationFilePath({ translationFilePath: string; }): string { const dirPath = getPluginI18nPath({ - i18nDir, + localizationDir, pluginName: plugin.name, pluginId: plugin.options.id, }); @@ -192,7 +192,7 @@ function getPluginTranslationFilePath({ } export async function writePluginTranslations({ - i18nDir, + localizationDir, plugin, translationFile, options, @@ -203,7 +203,7 @@ export async function writePluginTranslations({ }): Promise { const filePath = getPluginTranslationFilePath({ plugin, - i18nDir, + localizationDir, translationFilePath: translationFile.path, }); await writeTranslationFileContent({ @@ -214,7 +214,7 @@ export async function writePluginTranslations({ } export async function localizePluginTranslationFile({ - i18nDir, + localizationDir, plugin, translationFile, }: TranslationContext & { @@ -223,7 +223,7 @@ export async function localizePluginTranslationFile({ }): Promise { const filePath = getPluginTranslationFilePath({ plugin, - i18nDir, + localizationDir, translationFilePath: translationFile.path, }); From 4b0dd5c59f6e7740bd4b97927b051e9e0503b903 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Fri, 27 May 2022 18:52:06 +0800 Subject: [PATCH 3/4] fix test types --- .../src/__tests__/feed.test.ts | 1 + .../docusaurus-utils/src/__tests__/i18nUtils.test.ts | 5 +++++ packages/docusaurus/src/server/__tests__/i18n.test.ts | 9 ++++++--- .../server/translations/__tests__/translations.test.ts | 4 ---- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts index d7747d16300c..367872215282 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts @@ -19,6 +19,7 @@ const DefaultI18N: I18n = { currentLocale: 'en', locales: ['en'], defaultLocale: 'en', + path: '1i8n', localeConfigs: { en: { label: 'English', diff --git a/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts b/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts index 6e8f4e198a7e..c0b45f358568 100644 --- a/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts @@ -103,6 +103,7 @@ describe('localizePath', () => { path: '/baseUrl', i18n: { defaultLocale: 'en', + path: 'i18n', locales: ['en', 'fr'], currentLocale: 'fr', localeConfigs: {}, @@ -119,6 +120,7 @@ describe('localizePath', () => { path: '/baseFsPath', i18n: { defaultLocale: 'en', + path: 'i18n', locales: ['en', 'fr'], currentLocale: 'fr', localeConfigs: {}, @@ -135,6 +137,7 @@ describe('localizePath', () => { path: '/baseUrl/', i18n: { defaultLocale: 'en', + path: 'i18n', locales: ['en', 'fr'], currentLocale: 'en', localeConfigs: {}, @@ -151,6 +154,7 @@ describe('localizePath', () => { path: '/baseUrl/', i18n: { defaultLocale: 'en', + path: 'i18n', locales: ['en', 'fr'], currentLocale: 'en', localeConfigs: {}, @@ -166,6 +170,7 @@ describe('localizePath', () => { path: '/baseUrl/', i18n: { defaultLocale: 'en', + path: 'i18n', locales: ['en', 'fr'], currentLocale: 'en', localeConfigs: {}, diff --git a/packages/docusaurus/src/server/__tests__/i18n.test.ts b/packages/docusaurus/src/server/__tests__/i18n.test.ts index 8c99d006545c..2f7c5f9059ff 100644 --- a/packages/docusaurus/src/server/__tests__/i18n.test.ts +++ b/packages/docusaurus/src/server/__tests__/i18n.test.ts @@ -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}, ); } @@ -112,6 +111,7 @@ describe('loadI18n', () => { it('loads I18n for multi-lang config', async () => { await expect( loadI18nTest({ + path: 'i18n', defaultLocale: 'fr', locales: ['en', 'fr', 'de'], localeConfigs: {}, @@ -128,6 +128,7 @@ describe('loadI18n', () => { await expect( loadI18nTest( { + path: 'i18n', defaultLocale: 'fr', locales: ['en', 'fr', 'de'], localeConfigs: {}, @@ -146,6 +147,7 @@ describe('loadI18n', () => { await expect( loadI18nTest( { + path: 'i18n', defaultLocale: 'fr', locales: ['en', 'fr', 'de'], localeConfigs: { @@ -175,6 +177,7 @@ describe('loadI18n', () => { it('warns when trying to load undeclared locale', async () => { await loadI18nTest( { + path: 'i18n', defaultLocale: 'fr', locales: ['en', 'fr', 'de'], localeConfigs: {}, diff --git a/packages/docusaurus/src/server/translations/__tests__/translations.test.ts b/packages/docusaurus/src/server/translations/__tests__/translations.test.ts index 7d2ce1cb2811..a62aae849802 100644 --- a/packages/docusaurus/src/server/translations/__tests__/translations.test.ts +++ b/packages/docusaurus/src/server/translations/__tests__/translations.test.ts @@ -281,7 +281,6 @@ describe('writePluginTranslations', () => { await writePluginTranslations({ localizationDir, - locale: 'fr', translationFile: { path: 'my/translation/file', content: { @@ -384,7 +383,6 @@ describe('writePluginTranslations', () => { await expect(() => writePluginTranslations({ localizationDir, - locale: 'fr', translationFile: { path: 'my/translation/file.json', content: {}, @@ -420,7 +418,6 @@ describe('localizePluginTranslationFile', () => { const localizedTranslationFile = await localizePluginTranslationFile({ localizationDir, - locale: 'fr', translationFile, plugin: { name: 'my-plugin-name', @@ -453,7 +450,6 @@ describe('localizePluginTranslationFile', () => { const localizedTranslationFile = await localizePluginTranslationFile({ localizationDir, - locale: 'fr', translationFile, plugin: { name: 'my-plugin-name', From 070dda0822360730976e3d47687b39d61e52bc13 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Fri, 27 May 2022 19:48:34 +0800 Subject: [PATCH 4/4] fix test --- .../src/server/__tests__/__snapshots__/config.test.ts.snap | 1 + packages/docusaurus/src/server/__tests__/i18n.test.ts | 3 +++ 2 files changed, 4 insertions(+) diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap index 36c7ae200aec..64dfeff98eea 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap @@ -13,6 +13,7 @@ exports[`loadSiteConfig website with .cjs siteConfig 1`] = ` "locales": [ "en", ], + "path": "i18n", }, "noIndex": false, "onBrokenLinks": "throw", diff --git a/packages/docusaurus/src/server/__tests__/i18n.test.ts b/packages/docusaurus/src/server/__tests__/i18n.test.ts index 2f7c5f9059ff..8ef8fea9faf3 100644 --- a/packages/docusaurus/src/server/__tests__/i18n.test.ts +++ b/packages/docusaurus/src/server/__tests__/i18n.test.ts @@ -118,6 +118,7 @@ describe('loadI18n', () => { }), ).resolves.toEqual({ defaultLocale: 'fr', + path: 'i18n', locales: ['en', 'fr', 'de'], currentLocale: 'fr', localeConfigs: testLocaleConfigsFor(['en', 'fr', 'de']), @@ -137,6 +138,7 @@ describe('loadI18n', () => { ), ).resolves.toEqual({ defaultLocale: 'fr', + path: 'i18n', locales: ['en', 'fr', 'de'], currentLocale: 'de', localeConfigs: testLocaleConfigsFor(['en', 'fr', 'de']), @@ -159,6 +161,7 @@ describe('loadI18n', () => { ), ).resolves.toEqual({ defaultLocale: 'fr', + path: 'i18n', locales: ['en', 'fr', 'de'], currentLocale: 'de', localeConfigs: {