Skip to content

Commit 2febb76

Browse files
authored
feat(core): Add i18n.localeConfigs[locale].{url,baseUrl} config options (#11316)
Co-authored-by: slorber <[email protected]>
1 parent 12bcad9 commit 2febb76

File tree

29 files changed

+798
-299
lines changed

29 files changed

+798
-299
lines changed

.eslintrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ module.exports = {
214214
],
215215
'no-useless-escape': WARNING,
216216
'no-void': [ERROR, {allowAsStatement: true}],
217-
'prefer-destructuring': WARNING,
217+
'prefer-destructuring': OFF,
218218
'prefer-named-capture-group': WARNING,
219219
'prefer-template': WARNING,
220220
yoda: WARNING,

packages/docusaurus-plugin-pwa/src/registerSw.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@ import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
99
import {createStorageSlot} from '@docusaurus/theme-common';
1010

1111
// First: read the env variables (provided by Webpack)
12-
/* eslint-disable prefer-destructuring */
12+
1313
const PWA_SERVICE_WORKER_URL = process.env.PWA_SERVICE_WORKER_URL!;
1414
const PWA_OFFLINE_MODE_ACTIVATION_STRATEGIES = process.env
1515
.PWA_OFFLINE_MODE_ACTIVATION_STRATEGIES as unknown as (keyof typeof OfflineModeActivationStrategiesImplementations)[];
1616
const PWA_DEBUG = process.env.PWA_DEBUG;
17-
/* eslint-enable prefer-destructuring */
1817

1918
const MAX_MOBILE_WIDTH = 996;
2019

packages/docusaurus-theme-classic/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,39 +9,88 @@ import React, {type ReactNode} from 'react';
99
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
1010
import {useAlternatePageUtils} from '@docusaurus/theme-common/internal';
1111
import {translate} from '@docusaurus/Translate';
12-
import {useHistorySelector} from '@docusaurus/theme-common';
12+
import {mergeSearchStrings, useHistorySelector} from '@docusaurus/theme-common';
1313
import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem';
1414
import IconLanguage from '@theme/Icon/Language';
1515
import type {LinkLikeNavbarItemProps} from '@theme/NavbarItem';
1616
import type {Props} from '@theme/NavbarItem/LocaleDropdownNavbarItem';
1717

1818
import styles from './styles.module.css';
1919

20+
function useLocaleDropdownUtils() {
21+
const {
22+
siteConfig,
23+
i18n: {localeConfigs},
24+
} = useDocusaurusContext();
25+
const alternatePageUtils = useAlternatePageUtils();
26+
const search = useHistorySelector((history) => history.location.search);
27+
const hash = useHistorySelector((history) => history.location.hash);
28+
29+
const getLocaleConfig = (locale: string) => {
30+
const localeConfig = localeConfigs[locale];
31+
if (!localeConfig) {
32+
throw new Error(
33+
`Docusaurus bug, no locale config found for locale=${locale}`,
34+
);
35+
}
36+
return localeConfig;
37+
};
38+
39+
const getBaseURLForLocale = (locale: string) => {
40+
const localeConfig = getLocaleConfig(locale);
41+
const isSameDomain = localeConfig.url === siteConfig.url;
42+
if (isSameDomain) {
43+
// Shorter paths if localized sites are hosted on the same domain
44+
// This reduces HTML size a bit
45+
return `pathname://${alternatePageUtils.createUrl({
46+
locale,
47+
fullyQualified: false,
48+
})}`;
49+
}
50+
return alternatePageUtils.createUrl({
51+
locale,
52+
fullyQualified: true,
53+
});
54+
};
55+
56+
return {
57+
getURL: (locale: string, options: {queryString: string | undefined}) => {
58+
// We have 2 query strings because
59+
// - there's the current one
60+
// - there's one user can provide through navbar config
61+
// see https://github.com/facebook/docusaurus/pull/8915
62+
const finalSearch = mergeSearchStrings(
63+
[search, options.queryString],
64+
'append',
65+
);
66+
return `${getBaseURLForLocale(locale)}${finalSearch}${hash}`;
67+
},
68+
getLabel: (locale: string) => {
69+
return getLocaleConfig(locale).label;
70+
},
71+
getLang: (locale: string) => {
72+
return getLocaleConfig(locale).htmlLang;
73+
},
74+
};
75+
}
76+
2077
export default function LocaleDropdownNavbarItem({
2178
mobile,
2279
dropdownItemsBefore,
2380
dropdownItemsAfter,
24-
queryString = '',
81+
queryString,
2582
...props
2683
}: Props): ReactNode {
84+
const utils = useLocaleDropdownUtils();
85+
2786
const {
28-
i18n: {currentLocale, locales, localeConfigs},
87+
i18n: {currentLocale, locales},
2988
} = useDocusaurusContext();
30-
const alternatePageUtils = useAlternatePageUtils();
31-
const search = useHistorySelector((history) => history.location.search);
32-
const hash = useHistorySelector((history) => history.location.hash);
33-
3489
const localeItems = locales.map((locale): LinkLikeNavbarItemProps => {
35-
const baseTo = `pathname://${alternatePageUtils.createUrl({
36-
locale,
37-
fullyQualified: false,
38-
})}`;
39-
// preserve ?search#hash suffix on locale switches
40-
const to = `${baseTo}${search}${hash}${queryString}`;
4190
return {
42-
label: localeConfigs[locale]!.label,
43-
lang: localeConfigs[locale]!.htmlLang,
44-
to,
91+
label: utils.getLabel(locale),
92+
lang: utils.getLang(locale),
93+
to: utils.getURL(locale, {queryString}),
4594
target: '_self',
4695
autoAddBaseUrl: false,
4796
className:
@@ -66,7 +115,7 @@ export default function LocaleDropdownNavbarItem({
66115
id: 'theme.navbar.mobileLanguageDropdown.label',
67116
description: 'The label for the mobile language switcher dropdown',
68117
})
69-
: localeConfigs[currentLocale]!.label;
118+
: utils.getLabel(currentLocale);
70119

71120
return (
72121
<DropdownNavbarItem

packages/docusaurus-theme-common/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"devDependencies": {
4747
"@docusaurus/core": "3.8.1",
4848
"@docusaurus/types": "3.8.1",
49+
"@total-typescript/shoehorn": "^0.1.2",
4950
"fs-extra": "^11.1.1",
5051
"lodash": "^4.17.21"
5152
},

packages/docusaurus-theme-common/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ export {
124124
useQueryString,
125125
useQueryStringList,
126126
useClearQueryString,
127+
mergeSearchParams,
128+
mergeSearchStrings,
127129
} from './utils/historyUtils';
128130

129131
export {
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import {mergeSearchParams, mergeSearchStrings} from '../historyUtils';
9+
10+
describe('mergeSearchParams', () => {
11+
it('can append search params', () => {
12+
expect(
13+
mergeSearchParams(
14+
[
15+
new URLSearchParams('?key1=val1&key2=val2'),
16+
new URLSearchParams('key2=val2-bis&key3=val3'),
17+
new URLSearchParams(''),
18+
new URLSearchParams('?key3=val3-bis&key4=val4'),
19+
],
20+
'append',
21+
).toString(),
22+
).toBe(
23+
'key1=val1&key2=val2&key2=val2-bis&key3=val3&key3=val3-bis&key4=val4',
24+
);
25+
});
26+
27+
it('can overwrite search params', () => {
28+
expect(
29+
mergeSearchParams(
30+
[
31+
new URLSearchParams('?key1=val1&key2=val2'),
32+
new URLSearchParams('key2=val2-bis&key3=val3'),
33+
new URLSearchParams(''),
34+
new URLSearchParams('?key3=val3-bis&key4=val4'),
35+
],
36+
'set',
37+
).toString(),
38+
).toBe('key1=val1&key2=val2-bis&key3=val3-bis&key4=val4');
39+
});
40+
});
41+
42+
describe('mergeSearchStrings', () => {
43+
it('can append search params', () => {
44+
expect(
45+
mergeSearchStrings(
46+
[
47+
'?key1=val1&key2=val2',
48+
'key2=val2-bis&key3=val3',
49+
'',
50+
'?key3=val3-bis&key4=val4',
51+
],
52+
'append',
53+
),
54+
).toBe(
55+
'?key1=val1&key2=val2&key2=val2-bis&key3=val3&key3=val3-bis&key4=val4',
56+
);
57+
});
58+
59+
it('can overwrite search params', () => {
60+
expect(
61+
mergeSearchStrings(
62+
[
63+
'?key1=val1&key2=val2',
64+
'key2=val2-bis&key3=val3',
65+
'',
66+
'?key3=val3-bis&key4=val4',
67+
],
68+
'set',
69+
),
70+
).toBe('?key1=val1&key2=val2-bis&key3=val3-bis&key4=val4');
71+
});
72+
73+
it('automatically adds ? if there are params', () => {
74+
expect(mergeSearchStrings(['key1=val1'], 'append')).toBe('?key1=val1');
75+
});
76+
77+
it('automatically removes ? if there are no params', () => {
78+
expect(mergeSearchStrings([undefined, ''], 'append')).toBe('');
79+
});
80+
});

0 commit comments

Comments
 (0)