diff --git a/packages/docusaurus/bin/docusaurus.mjs b/packages/docusaurus/bin/docusaurus.mjs index 7c92dee44e92..f67687371257 100755 --- a/packages/docusaurus/bin/docusaurus.mjs +++ b/packages/docusaurus/bin/docusaurus.mjs @@ -33,6 +33,15 @@ process.env.NODE_ENV ??= 'development'; await beforeCli(); +/** + * @param {string} locale + * @param {string[]} locales + * @returns {string[]} + */ +function concatLocaleOptions(locale, locales = []) { + return locales.concat(locale); +} + cli.version(DOCUSAURUS_VERSION).usage(' [options]'); cli @@ -55,8 +64,9 @@ cli 'path to docusaurus config file (default: `[siteDir]/docusaurus.config.js`)', ) .option( - '-l, --locale ', - 'build the site in a specified locale. Build all known locales otherwise', + '-l, --locale ', + 'build the site in the specified locale(s). Build all known locales otherwise', + concatLocaleOptions, ) .option( '--no-minify', @@ -101,7 +111,8 @@ cli .description('Deploy website to GitHub pages.') .option( '-l, --locale ', - 'deploy the site in a specified locale. Deploy all known locales otherwise', + 'deploy the site in the specified locale(s). Deploy all known locales otherwise', + concatLocaleOptions, ) .option( '--out-dir ', diff --git a/packages/docusaurus/src/commands/build/build.ts b/packages/docusaurus/src/commands/build/build.ts index d0334e34bf80..1a7826444659 100644 --- a/packages/docusaurus/src/commands/build/build.ts +++ b/packages/docusaurus/src/commands/build/build.ts @@ -12,10 +12,8 @@ import {loadContext, type LoadContextParams} from '../../server/site'; import {loadI18n} from '../../server/i18n'; import {buildLocale, type BuildLocaleParams} from './buildLocale'; -export type BuildCLIOptions = Pick< - LoadContextParams, - 'config' | 'locale' | 'outDir' -> & { +export type BuildCLIOptions = Pick & { + locale?: [string, ...string[]]; bundleAnalyzer?: boolean; minify?: boolean; dev?: boolean; @@ -27,7 +25,7 @@ export async function build( ): Promise { process.env.BABEL_ENV = 'production'; process.env.NODE_ENV = 'production'; - process.env.DOCUSAURUS_CURRENT_LOCALE = cliOptions.locale; + process.env.DOCUSAURUS_CURRENT_LOCALE = cliOptions.locale?.[0]; if (cliOptions.dev) { logger.info`Building in dev mode`; process.env.BABEL_ENV = 'development'; @@ -57,6 +55,25 @@ export async function build( logger.info`Use code=${'npm run serve'} command to test your build locally.`; } +// We need the default locale to always be the 1st in the list. If we build it +// last, it would "erase" the localized sites built in sub-folders +function orderLocales({ + locales, + defaultLocale, +}: { + locales: [string, ...string[]]; + defaultLocale: string; +}): [string, ...string[]] { + if (locales.includes(defaultLocale)) { + return [ + defaultLocale, + ...locales.filter((locale) => locale !== defaultLocale), + ]; + } else { + return locales; + } +} + async function getLocalesToBuild({ siteDir, cliOptions, @@ -64,30 +81,25 @@ async function getLocalesToBuild({ siteDir: string; cliOptions: BuildCLIOptions; }): Promise<[string, ...string[]]> { - if (cliOptions.locale) { - return [cliOptions.locale]; - } + // We disable locale path localization if CLI has single "--locale" option + // yarn build --locale fr => baseUrl=/ instead of baseUrl=/fr/ + const localizePath = cliOptions.locale?.length === 1 ? false : undefined; const context = await loadContext({ siteDir, outDir: cliOptions.outDir, config: cliOptions.config, - locale: cliOptions.locale, - localizePath: cliOptions.locale ? false : undefined, + localizePath, }); - const i18n = await loadI18n(context.siteConfig, { - locale: cliOptions.locale, - }); - if (i18n.locales.length > 1) { - logger.info`Website will be built for all these locales: ${i18n.locales}`; - } - // We need the default locale to always be the 1st in the list. If we build it - // last, it would "erase" the localized sites built in sub-folders - return [ - i18n.defaultLocale, - ...i18n.locales.filter((locale) => locale !== i18n.defaultLocale), - ]; + const i18n = await loadI18n(context.siteConfig); + + const locales = cliOptions.locale ?? i18n.locales; + + return orderLocales({ + locales: locales as [string, ...string[]], + defaultLocale: i18n.defaultLocale, + }); } async function tryToBuildLocale(params: BuildLocaleParams) { diff --git a/packages/docusaurus/src/commands/build/buildLocale.ts b/packages/docusaurus/src/commands/build/buildLocale.ts index 1d8c30f219e9..83d6557b62c8 100644 --- a/packages/docusaurus/src/commands/build/buildLocale.ts +++ b/packages/docusaurus/src/commands/build/buildLocale.ts @@ -51,7 +51,7 @@ export async function buildLocale({ outDir: cliOptions.outDir, config: cliOptions.config, locale, - localizePath: cliOptions.locale ? false : undefined, + localizePath: cliOptions.locale?.length === 1 ? false : undefined, }), ); diff --git a/packages/docusaurus/src/commands/deploy.ts b/packages/docusaurus/src/commands/deploy.ts index 6db5bae9978c..4b91ce7f7878 100644 --- a/packages/docusaurus/src/commands/deploy.ts +++ b/packages/docusaurus/src/commands/deploy.ts @@ -14,10 +14,8 @@ import {hasSSHProtocol, buildSshUrl, buildHttpsUrl} from '@docusaurus/utils'; import {loadContext, type LoadContextParams} from '../server/site'; import {build} from './build/build'; -export type DeployCLIOptions = Pick< - LoadContextParams, - 'config' | 'locale' | 'outDir' -> & { +export type DeployCLIOptions = Pick & { + locale?: [string, ...string[]]; skipBuild?: boolean; targetDir?: string; }; diff --git a/packages/docusaurus/src/server/i18n.ts b/packages/docusaurus/src/server/i18n.ts index c44a65f41f0e..e53490fcc27f 100644 --- a/packages/docusaurus/src/server/i18n.ts +++ b/packages/docusaurus/src/server/i18n.ts @@ -88,11 +88,11 @@ export function getDefaultLocaleConfig(locale: string): I18nLocaleConfig { export async function loadI18n( config: DocusaurusConfig, - options: Pick, + options?: Pick, ): Promise { const {i18n: i18nConfig} = config; - const currentLocale = options.locale ?? i18nConfig.defaultLocale; + const currentLocale = options?.locale ?? i18nConfig.defaultLocale; if (!i18nConfig.locales.includes(currentLocale)) { logger.warn`The locale name=${currentLocale} was not found in your site configuration: Available locales are: ${i18nConfig.locales} diff --git a/website/docs/cli.mdx b/website/docs/cli.mdx index 5be24e5191b5..1ec8120b4992 100644 --- a/website/docs/cli.mdx +++ b/website/docs/cli.mdx @@ -90,7 +90,7 @@ Compiles your site for production. | `--bundle-analyzer` | `false` | Analyze your bundle with the [webpack bundle analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer). | | `--out-dir` | `build` | The full path for the new output directory, relative to the current workspace. | | `--config` | `undefined` | Path to Docusaurus config file, default to `[siteDir]/docusaurus.config.js` | -| `--locale` | | Build the site in the specified locale. If not specified, all known locales are built. | +| `--locale` | | Build the site in the specified locale(s). If not specified, all known locales are built. | | `--no-minify` | `false` | Build website without minimizing JS/CSS bundles. | :::info @@ -141,7 +141,7 @@ Deploys your site with [GitHub Pages](https://pages.github.com/). Check out the | Name | Default | Description | | --- | --- | --- | -| `--locale` | | Deploy the site in the specified locale. If not specified, all known locales are deployed. | +| `--locale` | | Deploy the site in the specified locale(s). If not specified, all known locales are deployed. | | `--out-dir` | `build` | The full path for the new output directory, relative to the current workspace. | | `--skip-build` | `false` | Deploy website without building it. This may be useful when using a custom deploy script. | | `--target-dir` | `.` | Path to the target directory to deploy to. |