瀏覽代碼

Expand AI Companion speech transcription to global locale coverage.

Default locale fallback now prioritizes the user's current and preferred languages, then scans all Apple-supported recognizer locales for better multilingual transcript generation.

Co-authored-by: Cursor <cursoragent@cursor.com>
huzaifahayat12 2 月之前
父節點
當前提交
2542f621e1
共有 1 個文件被更改,包括 44 次插入2 次删除
  1. 44 2
      meetings_app/Transcription/MeetingTranscriptionService.swift

+ 44 - 2
meetings_app/Transcription/MeetingTranscriptionService.swift

@@ -101,7 +101,7 @@ final class MeetingTranscriptionService {
         systemURL: URL?,
         chunkSeconds: TimeInterval = 30,
         overlapSeconds: TimeInterval = 0,
-        locales: [Locale] = [Locale(identifier: "en-US")],
+        locales: [Locale] = [],
         onProgress: (@Sendable (MeetingTranscriptionProgress) -> Void)? = nil
     ) async throws -> [TranscriptSegment] {
         try await requestAuthorization()
@@ -125,7 +125,7 @@ final class MeetingTranscriptionService {
         let counter = ProgressCounter(total: totalChunks, onProgress: onProgress)
         await counter.emitInitial()
 
-        let effectiveLocales = locales.isEmpty ? [Locale(identifier: "en-US")] : locales
+        let effectiveLocales = locales.isEmpty ? preferredLocalesForGlobalRecognition() : locales
 
         async let micSegments: [TranscriptSegment] = {
             guard let plan = micPlan else { return [] }
@@ -248,6 +248,48 @@ final class MeetingTranscriptionService {
         return ""
     }
 
+    private func preferredLocalesForGlobalRecognition() -> [Locale] {
+        let supported = SFSpeechRecognizer.supportedLocales()
+        guard supported.isEmpty == false else {
+            return [Locale.current, Locale(identifier: "en-US")]
+        }
+
+        let normalizedSupportedByIdentifier: [String: Locale] = Dictionary(
+            uniqueKeysWithValues: supported.map { locale in
+                (normalizeLocaleIdentifier(locale.identifier), locale)
+            }
+        )
+
+        var ordered: [Locale] = []
+        var seen = Set<String>()
+
+        func appendIfSupportedIdentifier(_ identifier: String) {
+            let normalized = normalizeLocaleIdentifier(identifier)
+            guard seen.contains(normalized) == false else { return }
+            guard let supportedLocale = normalizedSupportedByIdentifier[normalized] else { return }
+            seen.insert(normalized)
+            ordered.append(supportedLocale)
+        }
+
+        appendIfSupportedIdentifier(Locale.current.identifier)
+        for identifier in Locale.preferredLanguages {
+            appendIfSupportedIdentifier(identifier)
+        }
+
+        for locale in supported.sorted(by: { $0.identifier < $1.identifier }) {
+            appendIfSupportedIdentifier(locale.identifier)
+        }
+
+        if ordered.isEmpty {
+            return [Locale(identifier: "en-US")]
+        }
+        return ordered
+    }
+
+    private func normalizeLocaleIdentifier(_ identifier: String) -> String {
+        identifier.replacingOccurrences(of: "_", with: "-").lowercased()
+    }
+
     private func transcribeBuffer(buffer: AVAudioPCMBuffer, recognizer: SFSpeechRecognizer) async throws -> String {
         let request = SFSpeechAudioBufferRecognitionRequest()
         request.shouldReportPartialResults = false