Skip to content

Commit

Permalink
feat(core): allow customizing the i18n directory name
Browse files Browse the repository at this point in the history
  • Loading branch information
Josh-Cena committed May 25, 2022
1 parent d50fe3b commit 9fb2fc9
Show file tree
Hide file tree
Showing 25 changed files with 124 additions and 157 deletions.
Expand Up @@ -47,6 +47,7 @@ function getI18n(locale: string): I18n {
currentLocale: locale,
locales: [locale],
defaultLocale: locale,
path: 'i18n',
localeConfigs: {
[locale]: {
calendar: 'gregory',
Expand All @@ -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: '/',
Expand All @@ -81,6 +83,7 @@ const getPlugin = async (
siteConfig,
generatedFilesDir,
i18n,
i18nDir,
} as LoadContext,
validateOptions({
validate: normalizePluginOptions as Validate<
Expand Down
4 changes: 2 additions & 2 deletions packages/docusaurus-plugin-content-blog/src/index.ts
Expand Up @@ -59,15 +59,15 @@ export default async function pluginContentBlog(
siteDir,
siteConfig,
generatedFilesDir,
i18nDir,
i18n: {currentLocale},
} = context;
const {onBrokenMarkdownLinks, baseUrl} = siteConfig;

const contentPaths: BlogContentPaths = {
contentPath: path.resolve(siteDir, options.path),
contentPathLocalized: getPluginI18nPath({
siteDir,
locale: currentLocale,
i18nDir,
pluginName: 'docusaurus-plugin-content-blog',
pluginId: options.id,
}),
Expand Down
Binary file modified packages/docusaurus-plugin-content-docs/src/__tests__/cli.test.ts
Binary file not shown.
9 changes: 5 additions & 4 deletions packages/docusaurus-plugin-content-docs/src/cli.ts
Expand Up @@ -85,13 +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);
// Copy docs files.
const docsDir =
locale === i18n.defaultLocale
? path.resolve(siteDir, docsPath)
: getDocsDirPathLocalized({
siteDir,
locale,
i18nDir,
pluginId,
versionName: CURRENT_VERSION_NAME,
});
Expand All @@ -114,8 +116,7 @@ export async function cliDocsVersionCommand(
locale === i18n.defaultLocale
? getVersionDocsDirPath(siteDir, pluginId, version)
: getDocsDirPathLocalized({
siteDir,
locale,
i18nDir,
pluginId,
versionName: version,
});
Expand Down
Expand Up @@ -17,6 +17,7 @@ import type {
} from '@docusaurus/plugin-content-docs';

const DefaultI18N: I18n = {
path: 'i18n',
currentLocale: 'en',
locales: ['en'],
defaultLocale: 'en',
Expand All @@ -37,6 +38,7 @@ describe('readVersionsMetadata', () => {
siteDir: simpleSiteDir,
baseUrl: '/',
i18n: DefaultI18N,
i18nDir: path.join(simpleSiteDir, 'i18n/en'),
} as LoadContext;

const vCurrent: VersionMetadata = {
Expand Down Expand Up @@ -198,6 +200,7 @@ describe('readVersionsMetadata', () => {
siteDir: versionedSiteDir,
baseUrl: '/',
i18n: DefaultI18N,
i18nDir: path.join(versionedSiteDir, 'i18n/en'),
} as LoadContext;

const vCurrent: VersionMetadata = {
Expand Down Expand Up @@ -636,6 +639,7 @@ describe('readVersionsMetadata', () => {
siteDir: versionedSiteDir,
baseUrl: '/',
i18n: DefaultI18N,
i18nDir: path.join(versionedSiteDir, 'i18n/en'),
} as LoadContext;

const vCurrent: VersionMetadata = {
Expand Down
12 changes: 4 additions & 8 deletions packages/docusaurus-plugin-content-docs/src/versions/files.ts
Expand Up @@ -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: [
Expand Down Expand Up @@ -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,
});
Expand Down
Expand Up @@ -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,
})
Expand Down
Expand Up @@ -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",
Expand All @@ -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",
},
Expand Down
Expand Up @@ -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: {
Expand Down
10 changes: 2 additions & 8 deletions packages/docusaurus-plugin-content-pages/src/index.ts
Expand Up @@ -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,
}),
Expand Down
10 changes: 10 additions & 0 deletions packages/docusaurus-types/src/index.d.ts
Expand Up @@ -70,6 +70,11 @@ export type I18nConfig = {
* 3. Will be used for the `<link hrefLang="x-default">` 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. */
Expand Down Expand Up @@ -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
Expand Down
21 changes: 10 additions & 11 deletions packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts
Expand Up @@ -65,34 +65,33 @@ describe('getPluginI18nPath', () => {
it('gets correct path', () => {
expect(
getPluginI18nPath({
siteDir: __dirname,
locale: 'zh-Hans',
i18nDir: '<SITE_DIR>/i18n/zh-Hans',
pluginName: 'plugin-content-docs',
pluginId: 'community',
subPaths: ['foo'],
}),
).toMatchInlineSnapshot(
`"<PROJECT_ROOT>/packages/docusaurus-utils/src/__tests__/i18n/zh-Hans/plugin-content-docs-community/foo"`,
`"<SITE_DIR>/i18n/zh-Hans/plugin-content-docs-community/foo"`,
);
});
it('gets correct path for default plugin', () => {
expect(
getPluginI18nPath({
siteDir: __dirname,
locale: 'zh-Hans',
i18nDir: '<SITE_DIR>/i18n/zh-Hans',
pluginName: 'plugin-content-docs',
subPaths: ['foo'],
}).replace(__dirname, ''),
).toMatchInlineSnapshot(`"/i18n/zh-Hans/plugin-content-docs/foo"`);
}),
).toMatchInlineSnapshot(
`"<SITE_DIR>/i18n/zh-Hans/plugin-content-docs/foo"`,
);
});
it('gets correct path when no sub-paths', () => {
expect(
getPluginI18nPath({
siteDir: __dirname,
locale: 'zh-Hans',
i18nDir: '<SITE_DIR>/i18n/zh-Hans',
pluginName: 'plugin-content-docs',
}).replace(__dirname, ''),
).toMatchInlineSnapshot(`"/i18n/zh-Hans/plugin-content-docs"`);
}),
).toMatchInlineSnapshot(`"<SITE_DIR>/i18n/zh-Hans/plugin-content-docs"`);
});
});

Expand Down
2 changes: 1 addition & 1 deletion packages/docusaurus-utils/src/constants.ts
Expand Up @@ -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.
Expand Down
14 changes: 4 additions & 10 deletions packages/docusaurus-utils/src/i18nUtils.ts
Expand Up @@ -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,
Expand Down Expand Up @@ -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}`}`,
Expand Down
2 changes: 1 addition & 1 deletion packages/docusaurus-utils/src/index.ts
Expand Up @@ -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,
Expand Down
12 changes: 2 additions & 10 deletions packages/docusaurus/src/commands/start.ts
Expand Up @@ -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'> & {
Expand Down Expand Up @@ -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)) {
Expand All @@ -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,
Expand Down

0 comments on commit 9fb2fc9

Please sign in to comment.