Skip to content

Commit

Permalink
feat: allow customizing localization path of each locale (#7624)
Browse files Browse the repository at this point in the history
  • Loading branch information
Josh-Cena committed Jun 17, 2022
1 parent 39e3e37 commit 1b9bec1
Show file tree
Hide file tree
Showing 24 changed files with 254 additions and 30 deletions.
Expand Up @@ -26,6 +26,7 @@ const DefaultI18N: I18n = {
direction: 'ltr',
htmlLang: 'en',
calendar: 'gregory',
path: 'en',
},
},
};
Expand Down
Expand Up @@ -54,6 +54,7 @@ function getI18n(locale: string): I18n {
label: locale,
htmlLang: locale,
direction: 'ltr',
path: locale,
},
},
};
Expand All @@ -71,7 +72,11 @@ const getPlugin = async (
i18n: I18n = DefaultI18N,
) => {
const generatedFilesDir: string = path.resolve(siteDir, '.docusaurus');
const localizationDir = path.join(siteDir, i18n.path, i18n.currentLocale);
const localizationDir = path.join(
siteDir,
i18n.path,
i18n.localeConfigs[i18n.currentLocale]!.path,
);
const siteConfig = {
title: 'Hello',
baseUrl: '/',
Expand Down
Empty file.
Empty file.
Empty file.
Empty file.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -66,3 +66,12 @@ exports[`docsVersion second docs instance versioning 1`] = `
],
}
`;

exports[`docsVersion works with custom i18n paths 1`] = `
[
{
"dirName": ".",
"type": "autogenerated",
},
]
`;
Binary file not shown.
8 changes: 5 additions & 3 deletions packages/docusaurus-plugin-content-docs/src/cli.ts
Expand Up @@ -85,9 +85,11 @@ export async function cliDocsVersionCommand(

await Promise.all(
i18n.locales.map(async (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);
const localizationDir = path.resolve(
siteDir,
i18n.path,
i18n.localeConfigs[locale]!.path,
);
// Copy docs files.
const docsDir =
locale === i18n.defaultLocale
Expand Down
6 changes: 6 additions & 0 deletions packages/docusaurus-types/src/index.d.ts
Expand Up @@ -61,6 +61,12 @@ export type I18nLocaleConfig = {
* or `en-US` (`en` means `en-US`).
*/
calendar: string;
/**
* Root folder that all plugin localization folders of this locale are
* relative to. Will be resolved against `i18n.path`. Defaults to the locale's
* name.
*/
path: string;
};

export type I18nConfig = {
Expand Down
8 changes: 4 additions & 4 deletions packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts
Expand Up @@ -123,7 +123,7 @@ describe('localizePath', () => {
path: 'i18n',
locales: ['en', 'fr'],
currentLocale: 'fr',
localeConfigs: {},
localeConfigs: {fr: {path: 'fr'}, en: {path: 'en'}},
},
options: {localizePath: true},
}),
Expand All @@ -140,7 +140,7 @@ describe('localizePath', () => {
path: 'i18n',
locales: ['en', 'fr'],
currentLocale: 'en',
localeConfigs: {},
localeConfigs: {fr: {path: 'fr'}, en: {path: 'en'}},
},
options: {localizePath: true},
}),
Expand All @@ -157,7 +157,7 @@ describe('localizePath', () => {
path: 'i18n',
locales: ['en', 'fr'],
currentLocale: 'en',
localeConfigs: {},
localeConfigs: {fr: {path: 'fr'}, en: {path: 'en'}},
},
}),
).toBe('/baseUrl/');
Expand All @@ -173,7 +173,7 @@ describe('localizePath', () => {
path: 'i18n',
locales: ['en', 'fr'],
currentLocale: 'en',
localeConfigs: {},
localeConfigs: {fr: {path: 'fr'}, en: {path: 'en'}},
},
}),
).toBe('/baseUrl/');
Expand Down
9 changes: 7 additions & 2 deletions packages/docusaurus-utils/src/i18nUtils.ts
Expand Up @@ -68,6 +68,9 @@ export function getPluginI18nPath({
/**
* Takes a path and returns a localized a version (which is basically `path +
* i18n.currentLocale`).
*
* This is used to resolve the `outDir` and `baseUrl` of each locale; it is NOT
* used to determine plugin localization file locations.
*/
export function localizePath({
pathType,
Expand All @@ -94,13 +97,15 @@ export function localizePath({
};
}): string {
const shouldLocalizePath: boolean =
//
options.localizePath ?? i18n.currentLocale !== i18n.defaultLocale;

if (!shouldLocalizePath) {
return originalPath;
}
// FS paths need special care, for Windows support
// FS paths need special care, for Windows support. Note: we don't use the
// locale config's `path` here, because this function is used for resolving
// outDir, which must be the same as baseUrl. When we have the baseUrl config,
// we need to sync the two.
if (pathType === 'fs') {
return path.join(originalPath, i18n.currentLocale);
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

@@ -0,0 +1,118 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`load loads props for site with custom i18n path 1`] = `
{
"baseUrl": "/",
"codeTranslations": {},
"generatedFilesDir": "<PROJECT_ROOT>/packages/docusaurus/src/server/__tests__/__fixtures__/custom-i18n-site/.docusaurus",
"headTags": "",
"i18n": {
"currentLocale": "en",
"defaultLocale": "en",
"localeConfigs": {
"en": {
"calendar": "gregory",
"direction": "ltr",
"htmlLang": "en",
"label": "English",
"path": "en-custom",
},
"zh-Hans": {
"calendar": "gregory",
"direction": "ltr",
"htmlLang": "zh-Hans",
"label": "简体中文",
"path": "zh-Hans-custom",
},
},
"locales": [
"en",
"zh-Hans",
],
"path": "i18n",
},
"localizationDir": "<PROJECT_ROOT>/packages/docusaurus/src/server/__tests__/__fixtures__/custom-i18n-site/i18n/en-custom",
"outDir": "<PROJECT_ROOT>/packages/docusaurus/src/server/__tests__/__fixtures__/custom-i18n-site/build",
"plugins": [
{
"content": undefined,
"getClientModules": [Function],
"injectHtmlTags": [Function],
"name": "docusaurus-bootstrap-plugin",
"options": {
"id": "default",
},
"path": "<PROJECT_ROOT>/packages/docusaurus/src/server/__tests__/__fixtures__/custom-i18n-site",
"version": {
"type": "synthetic",
},
},
{
"configureWebpack": [Function],
"content": undefined,
"name": "docusaurus-mdx-fallback-plugin",
"options": {
"id": "default",
},
"path": ".",
"version": {
"type": "synthetic",
},
},
],
"postBodyTags": "",
"preBodyTags": "",
"routes": [],
"routesPaths": [
"/404.html",
],
"siteConfig": {
"baseUrl": "/",
"baseUrlIssueBanner": true,
"clientModules": [],
"customFields": {},
"i18n": {
"defaultLocale": "en",
"localeConfigs": {
"en": {
"direction": "ltr",
"path": "en-custom",
},
"zh-Hans": {
"direction": "ltr",
"path": "zh-Hans-custom",
},
},
"locales": [
"en",
"zh-Hans",
],
"path": "i18n",
},
"noIndex": false,
"onBrokenLinks": "throw",
"onBrokenMarkdownLinks": "warn",
"onDuplicateRoutes": "warn",
"plugins": [],
"presets": [],
"scripts": [],
"staticDirectories": [
"static",
],
"stylesheets": [],
"tagline": "",
"themeConfig": {},
"themes": [],
"title": "Site",
"titleDelimiter": "|",
"url": "https://example.com",
},
"siteConfigPath": "<PROJECT_ROOT>/packages/docusaurus/src/server/__tests__/__fixtures__/custom-i18n-site/docusaurus.config.js",
"siteDir": "<PROJECT_ROOT>/packages/docusaurus/src/server/__tests__/__fixtures__/custom-i18n-site",
"siteMetadata": {
"docusaurusVersion": "<CURRENT_VERSION>",
"pluginVersions": {},
"siteVersion": undefined,
},
}
`;
11 changes: 11 additions & 0 deletions packages/docusaurus/src/server/__tests__/i18n.test.ts
Expand Up @@ -32,62 +32,72 @@ describe('defaultLocaleConfig', () => {
direction: 'ltr',
htmlLang: 'fr',
calendar: 'gregory',
path: 'fr',
});
expect(getDefaultLocaleConfig('fr-FR')).toEqual({
label: 'Français (France)',
direction: 'ltr',
htmlLang: 'fr-FR',
calendar: 'gregory',
path: 'fr-FR',
});
expect(getDefaultLocaleConfig('en')).toEqual({
label: 'English',
direction: 'ltr',
htmlLang: 'en',
calendar: 'gregory',
path: 'en',
});
expect(getDefaultLocaleConfig('en-US')).toEqual({
label: 'American English',
direction: 'ltr',
htmlLang: 'en-US',
calendar: 'gregory',
path: 'en-US',
});
expect(getDefaultLocaleConfig('zh')).toEqual({
label: '中文',
direction: 'ltr',
htmlLang: 'zh',
calendar: 'gregory',
path: 'zh',
});
expect(getDefaultLocaleConfig('zh-CN')).toEqual({
label: '中文(中国)',
direction: 'ltr',
htmlLang: 'zh-CN',
calendar: 'gregory',
path: 'zh-CN',
});
expect(getDefaultLocaleConfig('en-US')).toEqual({
label: 'American English',
direction: 'ltr',
htmlLang: 'en-US',
calendar: 'gregory',
path: 'en-US',
});
expect(getDefaultLocaleConfig('fa')).toEqual({
// cSpell:ignore فارسی
label: 'فارسی',
direction: 'rtl',
htmlLang: 'fa',
calendar: 'gregory',
path: 'fa',
});
expect(getDefaultLocaleConfig('fa-IR')).toEqual({
// cSpell:ignore ایران فارسیا
label: 'فارسی (ایران)',
direction: 'rtl',
htmlLang: 'fa-IR',
calendar: 'gregory',
path: 'fa-IR',
});
expect(getDefaultLocaleConfig('en-US-u-ca-buddhist')).toEqual({
label: 'American English',
direction: 'ltr',
htmlLang: 'en-US-u-ca-buddhist',
calendar: 'buddhist',
path: 'en-US-u-ca-buddhist',
});
});
});
Expand Down Expand Up @@ -170,6 +180,7 @@ describe('loadI18n', () => {
direction: 'ltr',
htmlLang: 'fr',
calendar: 'gregory',
path: 'fr',
},
en: getDefaultLocaleConfig('en'),
de: getDefaultLocaleConfig('de'),
Expand Down
45 changes: 45 additions & 0 deletions packages/docusaurus/src/server/__tests__/index.test.ts
@@ -0,0 +1,45 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import path from 'path';
import {mergeWithCustomize} from 'webpack-merge';
import {loadSetup} from './testUtils';
import type {Props} from '@docusaurus/types';
import type {DeepPartial} from 'utility-types';

describe('load', () => {
it('loads props for site with custom i18n path', async () => {
const props = await loadSetup('custom-i18n-site');
expect(props).toMatchSnapshot();
const props2 = await loadSetup('custom-i18n-site', {locale: 'zh-Hans'});
expect(props2).toEqual(
mergeWithCustomize<DeepPartial<Props>>({
customizeArray(a, b, key) {
return ['routesPaths', 'plugins'].includes(key) ? b : undefined;
},
})(props, {
baseUrl: '/zh-Hans/',
i18n: {
currentLocale: 'zh-Hans',
},
localizationDir: path.join(
__dirname,
'__fixtures__/custom-i18n-site/i18n/zh-Hans-custom',
),
outDir: path.join(
__dirname,
'__fixtures__/custom-i18n-site/build/zh-Hans',
),
routesPaths: ['/zh-Hans/404.html'],
siteConfig: {
baseUrl: '/zh-Hans/',
},
plugins: props2.plugins,
}),
);
});
});

0 comments on commit 1b9bec1

Please sign in to comment.