Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow customizing localization path of each locale #7624

Merged
merged 3 commits into from Jun 17, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
Binary file modified packages/docusaurus-plugin-content-docs/src/__tests__/cli.test.ts
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
5 changes: 5 additions & 0 deletions packages/docusaurus-types/src/index.d.ts
Expand Up @@ -61,6 +61,11 @@ export type I18nLocaleConfig = {
* or `en-US` (`en` means `en-US`).
*/
calendar: string;
/**
* Root folder that all plugin localization folders 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
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
1 change: 1 addition & 0 deletions packages/docusaurus/src/server/i18n.ts
Expand Up @@ -26,6 +26,7 @@ export function getDefaultLocaleConfig(locale: string): I18nLocaleConfig {
htmlLang: locale,
// If the locale name includes -u-ca-xxx the calendar will be defined
calendar: new Intl.Locale(locale).calendar ?? 'gregory',
path: locale,
};
}

Expand Down
7 changes: 5 additions & 2 deletions packages/docusaurus/src/server/index.ts
Expand Up @@ -85,8 +85,11 @@ export async function loadContext(

const siteConfig: DocusaurusConfig = {...initialSiteConfig, baseUrl};

// TODO allow customizing localizationDir per-locale
const localizationDir = path.resolve(siteDir, i18n.path, i18n.currentLocale);
const localizationDir = path.resolve(
siteDir,
i18n.path,
i18n.localeConfigs[i18n.currentLocale]!.path,
);

const codeTranslationFileContent =
(await readCodeTranslationFileContent({localizationDir})) ?? {};
Expand Down
3 changes: 3 additions & 0 deletions website/docs/api/docusaurus.config.js.md
Expand Up @@ -136,12 +136,14 @@ module.exports = {
direction: 'ltr',
htmlLang: 'en-US',
calendar: 'gregory',
path: 'en',
},
fa: {
label: 'فارسی',
direction: 'rtl',
htmlLang: 'fa-IR',
calendar: 'persian',
path: 'fa',
},
},
},
Expand All @@ -155,6 +157,7 @@ module.exports = {
- `direction`: `ltr` (default) or `rtl` (for [right-to-left languages](https://developer.mozilla.org/en-US/docs/Glossary/rtl) like Farsi, Arabic, Hebrew, etc.). Used to select the locale's CSS and HTML meta attribute.
- `htmlLang`: BCP 47 language tag to use in `<html lang="...">` and in `<link ... hreflang="...">`
- `calendar`: the [calendar](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/calendar) used to calculate the date era. Note that it doesn't control the actual string displayed: `MM/DD/YYYY` and `DD/MM/YYYY` are both `gregory`. To choose the format (`DD/MM/YYYY` or `MM/DD/YYYY`), set your locale name to `en-GB` or `en-US` (`en` means `en-US`).
- `path`: Root folder that all plugin localization folders are relative to. Will be resolved against `i18n.path`. Defaults to the locale's name. Note: this has no effect on the locale's `baseUrl`—customization of base URL is a work-in-progress.
Josh-Cena marked this conversation as resolved.
Show resolved Hide resolved

### `noIndex` {#noIndex}

Expand Down