diff --git a/Keyboards/KeyboardsBase/KeyboardViewController.swift b/Keyboards/KeyboardsBase/KeyboardViewController.swift index 61dfee62..a2d2281c 100644 --- a/Keyboards/KeyboardsBase/KeyboardViewController.swift +++ b/Keyboards/KeyboardsBase/KeyboardViewController.swift @@ -2069,7 +2069,13 @@ class KeyboardViewController: UIInputViewController { autoCapAtStartOfProxy() if commandState == .invalid { - commandBar.text = commandPromptSpacing + invalidCommandMsgWikidata + // wordToTranslate is set by queryTranslation, verbToConjugate by triggerVerbConjugation. + let failedWord = wordToTranslate.isEmpty ? verbToConjugate : wordToTranslate + if let suggestion = didYouMeanSuggestion(for: failedWord) { + commandBar.text = commandPromptSpacing + suggestion + } else { + commandBar.text = commandPromptSpacing + invalidCommandMsgWikidata + } commandBar.isShowingInfoButton = true } else { commandBar.isShowingInfoButton = false @@ -2096,7 +2102,11 @@ class KeyboardViewController: UIInputViewController { loadKeys() proxy.insertText(selectedText) autoCapAtStartOfProxy() - commandBar.text = commandPromptSpacing + invalidCommandMsgWiktionary + if let suggestion = didYouMeanSuggestion(for: selectedText) { + commandBar.text = commandPromptSpacing + suggestion + } else { + commandBar.text = commandPromptSpacing + invalidCommandMsgWiktionary + } commandBar.isShowingInfoButton = true commandBar.textColor = keyCharColor return @@ -2130,7 +2140,11 @@ class KeyboardViewController: UIInputViewController { loadKeys() proxy.insertText(selectedText) autoCapAtStartOfProxy() - commandBar.text = commandPromptSpacing + invalidCommandMsgWikidata + if let suggestion = didYouMeanSuggestion(for: selectedText) { + commandBar.text = commandPromptSpacing + suggestion + } else { + commandBar.text = commandPromptSpacing + invalidCommandMsgWikidata + } commandBar.isShowingInfoButton = true commandBar.textColor = keyCharColor return @@ -2152,7 +2166,11 @@ class KeyboardViewController: UIInputViewController { if commandState == .invalid { proxy.insertText(selectedText) - commandBar.text = commandPromptSpacing + invalidCommandMsgWikidata + if let suggestion = didYouMeanSuggestion(for: selectedText) { + commandBar.text = commandPromptSpacing + suggestion + } else { + commandBar.text = commandPromptSpacing + invalidCommandMsgWikidata + } commandBar.isShowingInfoButton = true } else { commandBar.isShowingInfoButton = false diff --git a/Keyboards/KeyboardsBase/ScribeFunctionality/CommandVariables.swift b/Keyboards/KeyboardsBase/ScribeFunctionality/CommandVariables.swift index 43778e4f..6de2e0e4 100644 --- a/Keyboards/KeyboardsBase/ScribeFunctionality/CommandVariables.swift +++ b/Keyboards/KeyboardsBase/ScribeFunctionality/CommandVariables.swift @@ -182,3 +182,25 @@ var alreadyPluralMsg = "" /// The message shown on the download data button when no language data has been downloaded. var downloadDataMsg = "Please download language data" + +/// Returns a "Did you mean: X?" suggestion string for an invalid command input. +/// Progressively shortens the word to find the closest prefix match in the autocomplete lexicon. +/// +/// - Parameter word: the word that was not found. +/// - Returns: a suggestion string, or nil if no close match exists. +func didYouMeanSuggestion(for word: String) -> String? { + guard !word.isEmpty else { return nil } + + // Try progressively shorter prefixes (minimum 2 chars) to find a close match. + var prefix = word.lowercased() + while prefix.count >= 2 { + let suggestions = LanguageDBManager.shared.queryAutocompletions(word: prefix) + if let first = suggestions.first, !first.isEmpty { + // Only suggest if it's actually different from what was typed. + guard first.lowercased() != word.lowercased() else { return nil } + return "Did you mean: \(first)?" + } + prefix = String(prefix.dropLast()) + } + return nil +}