diff --git a/VoiceInk/Services/WordReplacementService.swift b/VoiceInk/Services/WordReplacementService.swift index 2c6fe85..1b84858 100644 --- a/VoiceInk/Services/WordReplacementService.swift +++ b/VoiceInk/Services/WordReplacementService.swift @@ -13,14 +13,14 @@ class WordReplacementService { var modifiedText = text - // Apply each replacement (case-insensitive, whole word) + // Apply replacements (case-insensitive) for (original, replacement) in replacements { let isPhrase = original.contains(" ") || original.trimmingCharacters(in: .whitespacesAndNewlines) != original - if isPhrase { - modifiedText = modifiedText.replacingOccurrences(of: original, with: replacement, options: .caseInsensitive) + if isPhrase || !usesWordBoundaries(for: original) { + modifiedText = modifiedText.replacingOccurrences(of: original, with: replacement, options: .caseInsensitive) } else { - // Create a regular expression that matches the word boundaries + // Use word boundaries for spaced languages let pattern = "\\b\(NSRegularExpression.escapedPattern(for: original))\\b" if let regex = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive) { let range = NSRange(modifiedText.startIndex..., in: modifiedText) @@ -36,4 +36,25 @@ class WordReplacementService { return modifiedText } + + private func usesWordBoundaries(for text: String) -> Bool { + // Returns false for languages without spaces (CJK, Thai), true for spaced languages + let nonSpacedScripts: [ClosedRange] = [ + 0x3040...0x309F, // Hiragana + 0x30A0...0x30FF, // Katakana + 0x4E00...0x9FFF, // CJK Unified Ideographs + 0xAC00...0xD7AF, // Hangul Syllables + 0x0E00...0x0E7F, // Thai + ] + + for scalar in text.unicodeScalars { + for range in nonSpacedScripts { + if range.contains(scalar.value) { + return false + } + } + } + + return true + } }