Skip to content

Commit

Permalink
feat: support i18n for search context labels
Browse files Browse the repository at this point in the history
  • Loading branch information
weareoutman committed Dec 19, 2023
1 parent 0be2e80 commit 83b05a2
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 85 deletions.
56 changes: 28 additions & 28 deletions README.md

Large diffs are not rendered by default.

74 changes: 46 additions & 28 deletions docusaurus-search-local/src/client/theme/SearchBar/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ import {
indexDocs,
searchContextByPaths,
hideSearchBarWithNoSearchContext,
useAllContextsWithNoSearchContext,
} from "../../utils/proxiedGenerated";
import LoadingRing from "../LoadingRing/LoadingRing";

import styles from "./SearchBar.module.css";
import { normalizeContextByPath } from "../../utils/normalizeContextByPath";

async function fetchAutoCompleteJS(): Promise<any> {
const autoCompleteModule = await import("@easyops-cn/autocomplete.js");
Expand Down Expand Up @@ -62,6 +64,7 @@ export default function SearchBar({
const isBrowser = useIsBrowser();
const {
siteConfig: { baseUrl },
i18n: { currentLocale },
} = useDocusaurusContext();

// It returns undefined for non-docs pages
Expand Down Expand Up @@ -161,39 +164,51 @@ export default function SearchBar({
const a = document.createElement("a");
const params = new URLSearchParams();

const seeAllResultsText = translate({
id: "theme.SearchBar.seeAll",
message: "See all results",
});

const seeAllResultsOutsideContextText = translate(
{
id: "theme.SearchBar.seeAllOutsideContext",
message: "See results outside {context}",
},
{ context: searchContext }
);

const seeAllResultsInContextText = translate(
{
id: "theme.SearchBar.searchInContext",
message: "See all results in {context}",
},
{ context: searchContext }
);

params.set("q", query);

let linkText;
if (searchContext && isEmpty) {
linkText = seeAllResultsOutsideContextText;
} else if (searchContext) {
linkText = seeAllResultsInContextText;
if (searchContext) {
const detailedSearchContext =
searchContext && Array.isArray(searchContextByPaths)
? searchContextByPaths.find((item) =>
typeof item === "string"
? item === searchContext
: item.path === searchContext
)
: searchContext;
const translatedSearchContext = detailedSearchContext
? normalizeContextByPath(detailedSearchContext, currentLocale).label
: searchContext;

if (useAllContextsWithNoSearchContext && isEmpty) {
linkText = translate(
{
id: "theme.SearchBar.seeAllOutsideContext",
message: "See results outside {context}",
},
{ context: translatedSearchContext }
);
} else {
linkText = translate(
{
id: "theme.SearchBar.searchInContext",
message: "See all results in {context}",
},
{ context: translatedSearchContext }
);
}
} else {
linkText = seeAllResultsText;
linkText = translate({
id: "theme.SearchBar.seeAll",
message: "See all results",
});
}

if (Array.isArray(searchContextByPaths) && !isEmpty) {
if (
searchContext &&
Array.isArray(searchContextByPaths) &&
(!useAllContextsWithNoSearchContext || !isEmpty)
) {
params.set("ctx", searchContext);
}

Expand Down Expand Up @@ -250,7 +265,10 @@ export default function SearchBar({
suggestion: SuggestionTemplate,
empty: EmptyTemplate,
footer: ({ query, isEmpty }: any) => {
if (isEmpty && !searchContext) {
if (
isEmpty &&
(!searchContext || !useAllContextsWithNoSearchContext)
) {
return;
}
const a = searchFooterLinkElement({ query, isEmpty });
Expand Down
37 changes: 18 additions & 19 deletions docusaurus-search-local/src/client/theme/SearchPage/SearchPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
} from "../../utils/proxiedGenerated";

import styles from "./SearchPage.module.css";
import { normalizeContextByPath } from "../../utils/normalizeContextByPath";

export default function SearchPage(): React.ReactElement {
return (
Expand All @@ -35,6 +36,7 @@ export default function SearchPage(): React.ReactElement {
function SearchPageContent(): React.ReactElement {
const {
siteConfig: { baseUrl },
i18n: { currentLocale },
} = useDocusaurusContext();

const { selectMessage } = usePluralForm();
Expand Down Expand Up @@ -106,10 +108,10 @@ function SearchPageContent(): React.ReactElement {

useEffect(() => {
async function doFetchIndexes() {
const { wrappedIndexes, zhDictionary } = await fetchIndexes(
versionUrl,
searchContext
);
const { wrappedIndexes, zhDictionary } =
searchContext || useAllContextsWithNoSearchContext
? await fetchIndexes(versionUrl, searchContext)
: { wrappedIndexes: [], zhDictionary: [] };
setSearchSource(() =>
SearchSourceFactory(wrappedIndexes, zhDictionary, 100)
);
Expand Down Expand Up @@ -166,22 +168,19 @@ function SearchPageContent(): React.ReactElement {
value={searchContext}
onChange={(e) => updateSearchContext(e.target.value)}
>
<option value="">
{useAllContextsWithNoSearchContext
? translate({
id: "theme.SearchPage.searchContext.everywhere",
message: "everywhere",
})
: ""}
</option>
{useAllContextsWithNoSearchContext && (
<option value="">
{translate({
id: "theme.SearchPage.searchContext.everywhere",
message: "everywhere",
})}
</option>
)}
{searchContextByPaths.map((context) => {
let label: string;
let path: string;
if (typeof context === "string") {
label = path = context;
} else {
({ label, path } = context);
}
const { label, path } = normalizeContextByPath(
context,
currentLocale
);
return (
<option key={path} value={path}>
{label}
Expand Down
18 changes: 14 additions & 4 deletions docusaurus-search-local/src/client/theme/hooks/useSearchQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import { useHistory, useLocation } from "@docusaurus/router";
import useIsBrowser from "@docusaurus/useIsBrowser";
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
import { searchContextByPaths } from "../../utils/proxiedGenerated";

const SEARCH_PARAM_QUERY = "q";
const SEARCH_PARAM_CONTEXT = "ctx";
Expand All @@ -34,21 +35,30 @@ function useSearchQuery(): any {
searchParams.delete(SEARCH_PARAM_QUERY);
}
return searchParams;
}
};

return {
searchValue,
searchContext,
searchContext:
searchContext &&
Array.isArray(searchContextByPaths) &&
searchContextByPaths.some((item) =>
typeof item === "string"
? item === searchContext
: item.path === searchContext
)
? searchContext
: "",
searchVersion,
updateSearchPath: (searchValue: string) => {
const searchParams = getSearchParams(searchValue);
history.replace({
search: searchParams.toString(),
});
},
updateSearchContext: (searchContext: string) => {
updateSearchContext: (value: string) => {
const searchParams = new URLSearchParams(location.search);
searchParams.set(SEARCH_PARAM_CONTEXT, searchContext);
searchParams.set(SEARCH_PARAM_CONTEXT, value);
history.replace({
search: searchParams.toString(),
});
Expand Down
36 changes: 36 additions & 0 deletions docusaurus-search-local/src/client/utils/normalizeContextByPath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
interface DetailedItem {
label: string | Record<string, string>;
path: string;
}

interface NormalizedItem {
path: string;
label: string;
}

export function normalizeContextByPath(
context: string | DetailedItem,
currentLocale: string
): NormalizedItem {
if (typeof context === "string") {
return {
label: context,
path: context,
};
} else {
const { label, path } = context;
if (typeof label === "string") {
return { label, path };
}
if (Object.prototype.hasOwnProperty.call(label, currentLocale)) {
return {
label: label[currentLocale],
path,
};
}
return {
label: path,
path,
};
}
}
2 changes: 1 addition & 1 deletion docusaurus-search-local/src/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ declare module "*/generated.js" {
export const indexDocs: boolean;
export const searchContextByPaths: (
| string
| { label: string; path: string }
| { label: string | Record<string, string>; path: string }
)[];
export const hideSearchBarWithNoSearchContext: boolean;
export const useAllContextsWithNoSearchContext: boolean;
Expand Down
5 changes: 4 additions & 1 deletion docusaurus-search-local/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,10 @@ export interface PluginOptions {
* Provide an list of sub-paths as separate search context, E.g.: `["docs", "community", "legacy/resources"]`.
* It will create multiple search indexes by these paths.
*/
searchContextByPaths?: (string | { label: string; path: string })[];
searchContextByPaths?: (
| string
| { label: string | Record<string, string>; path: string }
)[];

/**
* Whether to hide the search bar when no search context was matched.
Expand Down
10 changes: 8 additions & 2 deletions docusaurus-search-local/src/server/utils/validateOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,14 @@ const schema = Joi.object<PluginOptions>({
searchContextByPaths: Joi.array().items(
Joi.alternatives().try(
Joi.string(),
Joi.object<{ label: string; path: string }>({
label: Joi.string(),
Joi.object<{ label: string | Record<string, string>; path: string }>({
label: Joi.alternatives().try(
Joi.string(),
Joi.object<Record<string, string>>().pattern(
Joi.string(),
Joi.string()
)
),
path: Joi.string(),
})
)
Expand Down
13 changes: 11 additions & 2 deletions website-multi-docs/docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,17 @@ const config = {
docsDir: ["docs", "community"],
docsPluginIdForPreferredVersion: "product",
searchContextByPaths: [
"docs",
{ label: "Community", path: "community" },
{
label: "Tutorial",
path: "docs",
},
{
label: {
en: "Community",
zh: "社区",
},
path: "community",
},
],
hideSearchBarWithNoSearchContext: true,
}),
Expand Down

0 comments on commit 83b05a2

Please sign in to comment.