From cd9458427885282c9541de50041f5f5b5be1ec43 Mon Sep 17 00:00:00 2001 From: EthanHealy01 Date: Tue, 23 Sep 2025 23:51:28 +0100 Subject: [PATCH] add synonyms/tags to search --- frontend/src/components/tools/ToolPicker.tsx | 2 +- .../tools/automate/ToolSelector.tsx | 7 +- .../tools/toolPicker/ToolButton.tsx | 2 +- frontend/src/contexts/ToolWorkflowContext.tsx | 53 +++++++-- .../src/data/useTranslatedToolRegistry.tsx | 109 +++++++++++++----- 5 files changed, 129 insertions(+), 44 deletions(-) diff --git a/frontend/src/components/tools/ToolPicker.tsx b/frontend/src/components/tools/ToolPicker.tsx index 8d34394d7..4b0c54536 100644 --- a/frontend/src/components/tools/ToolPicker.tsx +++ b/frontend/src/components/tools/ToolPicker.tsx @@ -10,7 +10,7 @@ import { renderToolButtons } from "./shared/renderToolButtons"; interface ToolPickerProps { selectedToolKey: string | null; onSelect: (id: string) => void; - filteredTools: [string, ToolRegistryEntry][]; + filteredTools: Array<{ item: [string, ToolRegistryEntry]; matchedText?: string }>; isSearching?: boolean; } diff --git a/frontend/src/components/tools/automate/ToolSelector.tsx b/frontend/src/components/tools/automate/ToolSelector.tsx index 7d5faafc5..02ebef0c9 100644 --- a/frontend/src/components/tools/automate/ToolSelector.tsx +++ b/frontend/src/components/tools/automate/ToolSelector.tsx @@ -58,8 +58,13 @@ export default function ToolSelector({ return registry; }, [baseFilteredTools]); + // Transform filteredTools to the expected format for useToolSections + const transformedFilteredTools = useMemo(() => { + return filteredTools.map(([id, tool]) => ({ item: [id, tool] as [string, ToolRegistryEntry] })); + }, [filteredTools]); + // Use the same tool sections logic as the main ToolPicker - const { sections, searchGroups } = useToolSections(filteredTools); + const { sections, searchGroups } = useToolSections(transformedFilteredTools); // Determine what to display: search results or organized sections const isSearching = searchTerm.trim().length > 0; diff --git a/frontend/src/components/tools/toolPicker/ToolButton.tsx b/frontend/src/components/tools/toolPicker/ToolButton.tsx index fddade3c6..9f3d60d50 100644 --- a/frontend/src/components/tools/toolPicker/ToolButton.tsx +++ b/frontend/src/components/tools/toolPicker/ToolButton.tsx @@ -120,7 +120,7 @@ const ToolButton: React.FC = ({ id, tool, isSelected, onSelect, justify="flex-start" className="tool-button" aria-disabled={isUnavailable} - styles={{ root: { borderRadius: 0, color: "var(--tools-text-and-icon-color)", cursor: isUnavailable ? 'not-allowed' : undefined } }} + styles={{ root: { borderRadius: 0, color: "var(--tools-text-and-icon-color)", cursor: isUnavailable ? 'not-allowed' : undefined, overflow: 'visible' }, label: { overflow: 'visible' } }} > {buttonContent} diff --git a/frontend/src/contexts/ToolWorkflowContext.tsx b/frontend/src/contexts/ToolWorkflowContext.tsx index 5dca067e7..6178dda44 100644 --- a/frontend/src/contexts/ToolWorkflowContext.tsx +++ b/frontend/src/contexts/ToolWorkflowContext.tsx @@ -11,7 +11,7 @@ import { useNavigationActions, useNavigationState } from './NavigationContext'; import { ToolId, isValidToolId } from '../types/toolId'; import { useNavigationUrlSync } from '../hooks/useUrlSync'; import { getDefaultWorkbench } from '../types/workbench'; -import { rankByFuzzy, idToWords } from '../utils/fuzzySearch'; +import { idToWords, scoreMatch, minScoreForQuery } from '../utils/fuzzySearch'; // State interface interface ToolWorkflowState { @@ -227,17 +227,46 @@ export function ToolWorkflowProvider({ children }: ToolWorkflowProviderProps) { // Return in the new format even when not searching return entries.map(([id, tool]) => ({ item: [id, tool] as [string, ToolRegistryEntry] })); } - const ranked = rankByFuzzy(entries, state.searchQuery, [ - ([key]) => idToWords(key), - ([, v]) => v.name, - ([, v]) => v.description, - ([, v]) => v.synonyms?.join(' ') || '', - ]); - // Keep reasonable number in search view? Return all ranked to preserve grouping downstream - return ranked.map(r => ({ - item: r.item as [string, ToolRegistryEntry], - matchedText: r.matchedText - })); + + const threshold = minScoreForQuery(state.searchQuery); + const results: Array<{ item: [string, ToolRegistryEntry]; matchedText?: string; score: number }> = []; + + for (const [id, tool] of entries) { + let best = 0; + let matchedText = ''; + + const candidates: string[] = [ + idToWords(id), + tool.name || '', + tool.description || '' + ]; + for (const value of candidates) { + if (!value) continue; + const s = scoreMatch(state.searchQuery, value); + if (s > best) { + best = s; + matchedText = value; + } + } + + if (Array.isArray(tool.synonyms)) { + for (const synonym of tool.synonyms) { + if (!synonym) continue; + const s = scoreMatch(state.searchQuery, synonym); + if (s > best) { + best = s; + matchedText = synonym; + } + } + } + + if (best >= threshold) { + results.push({ item: [id, tool] as [string, ToolRegistryEntry], matchedText, score: best }); + } + } + + results.sort((a, b) => b.score - a.score); + return results.map(({ item, matchedText }) => ({ item, matchedText })); }, [toolRegistry, state.searchQuery]); const isPanelVisible = useMemo(() => diff --git a/frontend/src/data/useTranslatedToolRegistry.tsx b/frontend/src/data/useTranslatedToolRegistry.tsx index 007df8e24..009783300 100644 --- a/frontend/src/data/useTranslatedToolRegistry.tsx +++ b/frontend/src/data/useTranslatedToolRegistry.tsx @@ -146,6 +146,31 @@ export const CONVERT_SUPPORTED_FORMATS = [ "pdf", ]; +// Helper function to get translated synonyms for a tool +const getTranslatedSynonyms = (t: any, toolId: string): string[] => { + try { + const tagsKey = `${toolId}.tags`; + const tags = t(tagsKey); + + // If the translation key doesn't exist or returns the key itself, return empty array + if (!tags || tags === tagsKey) { + return []; + } + + // Split by comma and clean up the tags + return tags.split(',').map((tag: string) => tag.trim()).filter((tag: string) => tag.length > 0); + } catch (error) { + console.warn(`Failed to get translated synonyms for tool ${toolId}:`, error); + return []; + } +}; + +// Helper function to merge translated synonyms with existing synonyms +const mergeSynonyms = (t: any, toolId: string, existingSynonyms: string[] = []): string[] => { + const translatedSynonyms = getTranslatedSynonyms(t, toolId); + return [...translatedSynonyms, ...existingSynonyms]; +}; + // Hook to get the translated tool registry export function useFlatToolRegistry(): ToolRegistry { const { t } = useTranslation(); @@ -161,6 +186,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.certSign.desc", "Signs a PDF with a Certificate/Key (PEM/P12)"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.SIGNING, + synonyms: mergeSynonyms(t, "certSign"), }, sign: { icon: , @@ -169,7 +195,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.sign.desc", "Adds signature to PDF by drawing, text or image"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.SIGNING, - synonyms: ["signature", "autograph"] + synonyms: mergeSynonyms(t, "sign", ["signature", "autograph"]) }, // Document Security @@ -185,7 +211,7 @@ export function useFlatToolRegistry(): ToolRegistry { endpoints: ["add-password"], operationConfig: addPasswordOperationConfig, settingsComponent: AddPasswordSettings, - synonyms: ["lock", "secure"] + synonyms: mergeSynonyms(t, "addPassword", ["lock", "secure"]) }, watermark: { icon: , @@ -198,7 +224,7 @@ export function useFlatToolRegistry(): ToolRegistry { endpoints: ["add-watermark"], operationConfig: addWatermarkOperationConfig, settingsComponent: AddWatermarkSingleStepSettings, - synonyms: ["brand", "logo", "stamp"] + synonyms: mergeSynonyms(t, "watermark", ["brand", "logo", "stamp"]) }, addStamp: { icon: , @@ -207,6 +233,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.addStamp.desc", "Add text or add image stamps at set locations"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.DOCUMENT_SECURITY, + synonyms: mergeSynonyms(t, "addStamp"), }, sanitize: { icon: , @@ -219,7 +246,7 @@ export function useFlatToolRegistry(): ToolRegistry { endpoints: ["sanitize-pdf"], operationConfig: sanitizeOperationConfig, settingsComponent: SanitizeSettings, - synonyms: ["clean", "purge", "remove"] + synonyms: mergeSynonyms(t, "sanitize", ["clean", "purge", "remove"]) }, flatten: { icon: , @@ -232,7 +259,7 @@ export function useFlatToolRegistry(): ToolRegistry { endpoints: ["flatten"], operationConfig: flattenOperationConfig, settingsComponent: FlattenSettings, - synonyms: ["simplify", "flatten", "static"] + synonyms: mergeSynonyms(t, "flatten", ["simplify", "flatten", "static"]) }, unlockPDFForms: { icon: , @@ -245,6 +272,7 @@ export function useFlatToolRegistry(): ToolRegistry { endpoints: ["unlock-pdf-forms"], operationConfig: unlockPdfFormsOperationConfig, settingsComponent: UnlockPdfFormsSettings, + synonyms: mergeSynonyms(t, "unlockPDFForms"), }, manageCertificates: { icon: , @@ -256,6 +284,7 @@ export function useFlatToolRegistry(): ToolRegistry { ), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.DOCUMENT_SECURITY, + synonyms: mergeSynonyms(t, "manageCertificates"), }, changePermissions: { icon: , @@ -268,6 +297,7 @@ export function useFlatToolRegistry(): ToolRegistry { endpoints: ["add-password"], operationConfig: changePermissionsOperationConfig, settingsComponent: ChangePermissionsSettings, + synonyms: mergeSynonyms(t, "changePermissions"), }, // Verification @@ -278,6 +308,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.getPdfInfo.desc", "Grabs any and all information possible on PDFs"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.VERIFICATION, + synonyms: mergeSynonyms(t, "getPdfInfo"), }, validateSignature: { icon: , @@ -286,6 +317,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.validateSignature.desc", "Verify digital signatures and certificates in PDF documents"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.VERIFICATION, + synonyms: mergeSynonyms(t, "validateSignature"), }, // Document Review @@ -301,7 +333,7 @@ export function useFlatToolRegistry(): ToolRegistry { ), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.DOCUMENT_REVIEW, - synonyms: ["view", "open", "display"] + synonyms: mergeSynonyms(t, "read", ["view", "open", "display"]) }, changeMetadata: { icon: , @@ -314,7 +346,7 @@ export function useFlatToolRegistry(): ToolRegistry { endpoints: ["update-metadata"], operationConfig: changeMetadataOperationConfig, settingsComponent: ChangeMetadataSingleStep, - synonyms: ["edit", "modify", "update"] + synonyms: mergeSynonyms(t, "changeMetadata", ["edit", "modify", "update"]) }, // Page Formatting @@ -325,7 +357,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.crop.desc", "Crop a PDF to reduce its size (maintains text!)"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.PAGE_FORMATTING, - synonyms: ["trim", "cut", "resize"] + synonyms: mergeSynonyms(t, "crop", ["trim", "cut", "resize"]) }, rotate: { icon: , @@ -338,7 +370,7 @@ export function useFlatToolRegistry(): ToolRegistry { endpoints: ["rotate-pdf"], operationConfig: rotateOperationConfig, settingsComponent: RotateSettings, - synonyms: ["turn", "flip", "orient"] + synonyms: mergeSynonyms(t, "rotate", ["turn", "flip", "orient"]) }, split: { icon: , @@ -349,7 +381,7 @@ export function useFlatToolRegistry(): ToolRegistry { subcategoryId: SubcategoryId.PAGE_FORMATTING, operationConfig: splitOperationConfig, settingsComponent: SplitSettings, - synonyms: ["divide", "separate", "cut"] + synonyms: mergeSynonyms(t, "split", ["divide", "separate", "cut"]) }, reorganizePages: { icon: , @@ -362,7 +394,7 @@ export function useFlatToolRegistry(): ToolRegistry { ), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.PAGE_FORMATTING, - synonyms: ["rearrange", "reorder", "organize"] + synonyms: mergeSynonyms(t, "reorganizePages", ["rearrange", "reorder", "organize"]) }, scalePages: { icon: , @@ -375,7 +407,7 @@ export function useFlatToolRegistry(): ToolRegistry { endpoints: ["scale-pages"], operationConfig: adjustPageScaleOperationConfig, settingsComponent: AdjustPageScaleSettings, - synonyms: ["resize", "adjust", "scale"] + synonyms: mergeSynonyms(t, "scalePages", ["resize", "adjust", "scale"]) }, addPageNumbers: { icon: , @@ -385,7 +417,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.addPageNumbers.desc", "Add Page numbers throughout a document in a set location"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.PAGE_FORMATTING, - synonyms: ["number", "pagination", "count"] + synonyms: mergeSynonyms(t, "addPageNumbers", ["number", "pagination", "count"]) }, pageLayout: { icon: , @@ -395,7 +427,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.pageLayout.desc", "Merge multiple pages of a PDF document into a single page"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.PAGE_FORMATTING, - synonyms: ["layout", "arrange", "combine"] + synonyms: mergeSynonyms(t, "pageLayout", ["layout", "arrange", "combine"]) }, pdfToSinglePage: { icon: , @@ -409,7 +441,7 @@ export function useFlatToolRegistry(): ToolRegistry { urlPath: '/pdf-to-single-page', endpoints: ["pdf-to-single-page"], operationConfig: singleLargePageOperationConfig, - synonyms: ["combine", "merge", "single"] + synonyms: mergeSynonyms(t, "pdfToSinglePage", ["combine", "merge", "single"]) }, addAttachments: { icon: , @@ -419,7 +451,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.addAttachments.desc", "Add or remove embedded files (attachments) to/from a PDF"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.PAGE_FORMATTING, - synonyms: ["embed", "attach", "include"] + synonyms: mergeSynonyms(t, "addAttachments", ["embed", "attach", "include"]) }, // Extraction @@ -431,7 +463,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.extractPages.desc", "Extract specific pages from a PDF document"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.EXTRACTION, - synonyms: ["pull", "select", "copy"] + synonyms: mergeSynonyms(t, "extractPages", ["pull", "select", "copy"]) }, extractImages: { icon: , @@ -440,7 +472,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.extractImages.desc", "Extract images from PDF documents"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.EXTRACTION, - synonyms: ["pull", "save", "export"] + synonyms: mergeSynonyms(t, "extractImages", ["pull", "save", "export"]) }, // Removal @@ -454,7 +486,7 @@ export function useFlatToolRegistry(): ToolRegistry { subcategoryId: SubcategoryId.REMOVAL, maxFiles: 1, endpoints: ["remove-pages"], - synonyms: ["delete", "extract", "exclude"] + synonyms: mergeSynonyms(t, "removePages", ["delete", "extract", "exclude"]) }, removeBlanks: { icon: , @@ -465,7 +497,7 @@ export function useFlatToolRegistry(): ToolRegistry { subcategoryId: SubcategoryId.REMOVAL, maxFiles: 1, endpoints: ["remove-blanks"], - synonyms: ["delete", "clean", "empty"] + synonyms: mergeSynonyms(t, "removeBlanks", ["delete", "clean", "empty"]) }, removeAnnotations: { icon: , @@ -474,7 +506,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.removeAnnotations.desc", "Remove annotations and comments from PDF documents"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.REMOVAL, - synonyms: ["delete", "clean", "strip"] + synonyms: mergeSynonyms(t, "removeAnnotations", ["delete", "clean", "strip"]) }, removeImage: { icon: , @@ -483,6 +515,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.removeImage.desc", "Remove images from PDF documents"), categoryId: ToolCategoryId.STANDARD_TOOLS, subcategoryId: SubcategoryId.REMOVAL, + synonyms: mergeSynonyms(t, "removeImage"), }, removePassword: { icon: , @@ -495,7 +528,7 @@ export function useFlatToolRegistry(): ToolRegistry { maxFiles: -1, operationConfig: removePasswordOperationConfig, settingsComponent: RemovePasswordSettings, - synonyms: ["unlock"] + synonyms: mergeSynonyms(t, "removePassword", ["unlock"]) }, removeCertSign: { icon: , @@ -507,6 +540,7 @@ export function useFlatToolRegistry(): ToolRegistry { maxFiles: -1, endpoints: ["remove-certificate-sign"], operationConfig: removeCertificateSignOperationConfig, + synonyms: mergeSynonyms(t, "removeCertSign"), }, // Automation @@ -524,6 +558,7 @@ export function useFlatToolRegistry(): ToolRegistry { maxFiles: -1, supportedFormats: CONVERT_SUPPORTED_FORMATS, endpoints: ["handleData"], + synonyms: mergeSynonyms(t, "automate"), }, autoRename: { icon: , @@ -535,6 +570,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.autoRename.desc", "Automatically rename PDF files based on their content"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.AUTOMATION, + synonyms: mergeSynonyms(t, "autoRename"), }, autoSplitPDF: { icon: , @@ -543,6 +579,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.autoSplitPDF.desc", "Automatically split PDF pages based on content detection"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.AUTOMATION, + synonyms: mergeSynonyms(t, "autoSplitPDF"), }, autoSizeSplitPDF: { icon: , @@ -551,6 +588,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.autoSizeSplitPDF.desc", "Automatically split PDFs by file size or page count"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.AUTOMATION, + synonyms: mergeSynonyms(t, "autoSizeSplitPDF"), }, // Advanced Formatting @@ -562,6 +600,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.adjustContrast.desc", "Adjust colors and contrast of PDF documents"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.ADVANCED_FORMATTING, + synonyms: mergeSynonyms(t, "adjustContrast"), }, repair: { icon: , @@ -574,7 +613,7 @@ export function useFlatToolRegistry(): ToolRegistry { endpoints: ["repair"], operationConfig: repairOperationConfig, settingsComponent: RepairSettings, - synonyms: ["fix", "restore"] + synonyms: mergeSynonyms(t, "repair", ["fix", "restore"]) }, scannerImageSplit: { icon: , @@ -583,6 +622,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.scannerImageSplit.desc", "Detect and split scanned photos into separate pages"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.ADVANCED_FORMATTING, + synonyms: mergeSynonyms(t, "ScannerImageSplit"), }, overlayPdfs: { icon: , @@ -591,6 +631,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.overlayPdfs.desc", "Overlay one PDF on top of another"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.ADVANCED_FORMATTING, + synonyms: mergeSynonyms(t, "overlayPdfs"), }, replaceColorPdf: { icon: , @@ -599,6 +640,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.replaceColorPdf.desc", "Replace or invert colors in PDF documents"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.ADVANCED_FORMATTING, + synonyms: mergeSynonyms(t, "replaceColorPdf"), }, addImage: { icon: , @@ -607,6 +649,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.addImage.desc", "Add images to PDF documents"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.ADVANCED_FORMATTING, + synonyms: mergeSynonyms(t, "addImage"), }, editTableOfContents: { icon: , @@ -615,6 +658,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.editTableOfContents.desc", "Add or edit bookmarks and table of contents in PDF documents"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.ADVANCED_FORMATTING, + synonyms: mergeSynonyms(t, "editTableOfContents"), }, fakeScan: { icon: , @@ -623,6 +667,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.fakeScan.desc", "Create a PDF that looks like it was scanned"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.ADVANCED_FORMATTING, + synonyms: mergeSynonyms(t, "fakeScan"), }, // Developer Tools @@ -634,6 +679,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.showJS.desc", "Extract and display JavaScript code from PDF documents"), categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.DEVELOPER_TOOLS, + synonyms: mergeSynonyms(t, "showJS"), }, devApi: { icon: , @@ -643,6 +689,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.DEVELOPER_TOOLS, link: "https://stirlingpdf.io/swagger-ui/5.21.0/index.html", + synonyms: mergeSynonyms(t, "devApi", ["api"]), }, devFolderScanning: { icon: , @@ -652,6 +699,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.DEVELOPER_TOOLS, link: "https://docs.stirlingpdf.com/Advanced%20Configuration/Folder%20Scanning/", + synonyms: mergeSynonyms(t, "devFolderScanning"), }, devSsoGuide: { icon: , @@ -661,6 +709,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.DEVELOPER_TOOLS, link: "https://docs.stirlingpdf.com/Advanced%20Configuration/Single%20Sign-On%20Configuration", + synonyms: mergeSynonyms(t, "devSsoGuide"), }, devAirgapped: { icon: , @@ -670,6 +719,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.ADVANCED_TOOLS, subcategoryId: SubcategoryId.DEVELOPER_TOOLS, link: "https://docs.stirlingpdf.com/Pro/#activation", + synonyms: mergeSynonyms(t, "devAirgapped"), }, // Recommended Tools @@ -680,7 +730,7 @@ export function useFlatToolRegistry(): ToolRegistry { description: t("home.compare.desc", "Compare two PDF documents and highlight differences"), categoryId: ToolCategoryId.RECOMMENDED_TOOLS, subcategoryId: SubcategoryId.GENERAL, - synonyms: ["difference"] + synonyms: mergeSynonyms(t, "compare", ["difference"]) }, compress: { icon: , @@ -692,7 +742,7 @@ export function useFlatToolRegistry(): ToolRegistry { maxFiles: -1, operationConfig: compressOperationConfig, settingsComponent: CompressSettings, - synonyms: ["shrink", "reduce", "optimize"] + synonyms: mergeSynonyms(t, "compress", ["shrink", "reduce", "optimize"]) }, convert: { icon: , @@ -722,7 +772,7 @@ export function useFlatToolRegistry(): ToolRegistry { operationConfig: convertOperationConfig, settingsComponent: ConvertSettings, - synonyms: ["transform", "change"] + synonyms: mergeSynonyms(t, "convert", ["transform", "change"]) }, merge: { icon: , @@ -735,7 +785,7 @@ export function useFlatToolRegistry(): ToolRegistry { endpoints: ["merge-pdfs"], operationConfig: mergeOperationConfig, settingsComponent: MergeSettings, - synonyms: ["combine", "join", "unite"] + synonyms: mergeSynonyms(t, "merge", ["combine", "join", "unite"]) }, multiTool: { icon: , @@ -746,6 +796,7 @@ export function useFlatToolRegistry(): ToolRegistry { categoryId: ToolCategoryId.RECOMMENDED_TOOLS, subcategoryId: SubcategoryId.GENERAL, maxFiles: -1, + synonyms: mergeSynonyms(t, "multiTool", ["multiple", "tools"]), }, ocr: { icon: , @@ -758,7 +809,7 @@ export function useFlatToolRegistry(): ToolRegistry { urlPath: '/ocr-pdf', operationConfig: ocrOperationConfig, settingsComponent: OCRSettings, - synonyms: ["extract", "scan"] + synonyms: mergeSynonyms(t, "ocr", ["extract", "scan"]) }, redact: { icon: , @@ -771,7 +822,7 @@ export function useFlatToolRegistry(): ToolRegistry { endpoints: ["auto-redact"], operationConfig: redactOperationConfig, settingsComponent: RedactSingleStepSettings, - synonyms: ["censor", "blackout", "hide"] + synonyms: mergeSynonyms(t, "redact", ["censor", "blackout", "hide"]) }, };