Kaynağa Gözat

Add multilingual support for BG announcements with language selection in settings

Jonas Björkert 2 yıl önce
ebeveyn
işleme
728f8dfb43

+ 41 - 6
LoopFollow/Controllers/Alarms.swift

@@ -919,6 +919,35 @@ extension MainViewController {
         print("No condition met for speaking.")
         print("No condition met for speaking.")
     }
     }
     
     
+    struct AnnouncementTexts {
+        var stable: String
+        var down: String
+        var up: String
+        var currentBGIs: String
+        var andItIs: String
+        
+        static func forLanguage(_ language: String) -> AnnouncementTexts {
+            switch language {
+            case "sv":
+                return AnnouncementTexts(stable: "stabil", down: "nedåt", up: "uppåt", currentBGIs: "Aktuellt BG är", andItIs: "och det är")
+            case "en": fallthrough
+            default:
+                return AnnouncementTexts(stable: "stable", down: "down", up: "up", currentBGIs: "Current BG is", andItIs: "and it is")
+            }
+        }
+    }
+    
+    struct LanguageVoiceMapping {
+        static let voiceLanguageMap: [String: String] = [
+            "en": "en-US",
+            "sv": "sv-SE"
+        ]
+        
+        static func voiceLanguageCode(forAppLanguage appLanguage: String) -> String {
+            return voiceLanguageMap[appLanguage, default: "en-US"]
+        }
+    }
+
     // Speaks the current blood glucose value and the change from the previous value.
     // Speaks the current blood glucose value and the change from the previous value.
     // Repeated calls to the function within 30 seconds are prevented.
     // Repeated calls to the function within 30 seconds are prevented.
     func speakBG(currentValue: Int, previousValue: Int) {
     func speakBG(currentValue: Int, previousValue: Int) {
@@ -940,17 +969,23 @@ extension MainViewController {
         let negligibleThreshold = 3
         let negligibleThreshold = 3
         let differenceText: String
         let differenceText: String
 
 
+        let preferredLanguage = UserDefaultsRepository.speakLanguage.value
+        let voiceLanguageCode = LanguageVoiceMapping.voiceLanguageCode(forAppLanguage: preferredLanguage)
+
+        let texts = AnnouncementTexts.forLanguage(preferredLanguage)
+        
         if abs(bloodGlucoseDifference) <= negligibleThreshold {
         if abs(bloodGlucoseDifference) <= negligibleThreshold {
-            differenceText = "stable"
+            differenceText = texts.stable
         } else {
         } else {
-            let direction = bloodGlucoseDifference < 0 ? "down" : "up"
+            let directionText = bloodGlucoseDifference < 0 ? texts.down : texts.up
             let absoluteDifference = bgUnits.toDisplayUnits(String(abs(bloodGlucoseDifference)))
             let absoluteDifference = bgUnits.toDisplayUnits(String(abs(bloodGlucoseDifference)))
-            differenceText = "\(direction) \(absoluteDifference)"
+            differenceText = "\(directionText) \(absoluteDifference)"
         }
         }
-
-        let announcementText = "Current BG is \(bgUnits.toDisplayUnits(String(currentValue))), and it is \(differenceText)"
+        
+        let announcementText = "\(texts.currentBGIs) \(bgUnits.toDisplayUnits(String(currentValue))), \(texts.andItIs) \(differenceText)"
         let speechUtterance = AVSpeechUtterance(string: announcementText)
         let speechUtterance = AVSpeechUtterance(string: announcementText)
-        speechUtterance.voice = AVSpeechSynthesisVoice(language: "en-US")
+        speechUtterance.voice = AVSpeechSynthesisVoice(language: voiceLanguageCode)
+        
         speechSynthesizer.speak(speechUtterance)
         speechSynthesizer.speak(speechUtterance)
     }
     }
     
     

+ 20 - 0
LoopFollow/ViewControllers/GeneralSettingsViewController.swift

@@ -160,6 +160,26 @@ class GeneralSettingsViewController: FormViewController {
            self?.updateSpeakBGSettingsVisibility()
            self?.updateSpeakBGSettingsVisibility()
        }
        }
        
        
+       <<< PushRow<String>("speakLanguage") { row in
+           row.title = "Speaking Language"
+           row.options = ["en", "sv"]
+           row.value = UserDefaultsRepository.speakLanguage.value
+           row.displayValueFor = { value in
+               switch value {
+               case "sv": return "Swedish"
+               case "en": fallthrough
+               default: return "English"
+               }
+           }
+           row.hidden = Condition.function(["speakBG"], { form in
+               let speakBGRow: SwitchRow! = form.rowBy(tag: "speakBG")
+               return !(speakBGRow.value ?? false)
+           })
+       }.onChange { row in
+           guard let value = row.value else { return }
+           UserDefaultsRepository.speakLanguage.value = value
+       }
+       
        <<< SwitchRow("speakBGAlways") { row in
        <<< SwitchRow("speakBGAlways") { row in
            row.title = "Always"
            row.title = "Always"
            row.value = UserDefaultsRepository.speakBGAlways.value
            row.value = UserDefaultsRepository.speakBGAlways.value

+ 1 - 0
LoopFollow/ViewControllers/MainViewController.swift

@@ -277,6 +277,7 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
         restartAllTimers()
         restartAllTimers()
         currentCage = nil
         currentCage = nil
         currentSage = nil
         currentSage = nil
+        lastSpeechTime = nil
         refreshControl.endRefreshing()
         refreshControl.endRefreshing()
     }
     }
     
     

+ 1 - 0
LoopFollow/repository/UserDefaults.swift

@@ -83,6 +83,7 @@ class UserDefaultsRepository {
     static let speakLowBGLimit = UserDefaultsValue<Float>(key: "speakLowBGLimit", default: 72.0)
     static let speakLowBGLimit = UserDefaultsValue<Float>(key: "speakLowBGLimit", default: 72.0)
     static let speakHighBGLimit = UserDefaultsValue<Float>(key: "speakHighBGLimit", default: 180.0)
     static let speakHighBGLimit = UserDefaultsValue<Float>(key: "speakHighBGLimit", default: 180.0)
     static let speakHighBG = UserDefaultsValue<Bool>(key: "speakHighBG", default: false)
     static let speakHighBG = UserDefaultsValue<Bool>(key: "speakHighBG", default: false)
+    static let speakLanguage = UserDefaultsValue<String>(key: "speakLanguage", default: "en")
     static let showDisplayName = UserDefaultsValue<Bool>(key: "showDisplayName", default: false)
     static let showDisplayName = UserDefaultsValue<Bool>(key: "showDisplayName", default: false)
     static let backgroundRefreshFrequency = UserDefaultsValue<Double>(key: "backgroundRefreshFrequency", default: 1)
     static let backgroundRefreshFrequency = UserDefaultsValue<Double>(key: "backgroundRefreshFrequency", default: 1)
     static let backgroundRefresh = UserDefaultsValue<Bool>(key: "backgroundRefresh", default: true)
     static let backgroundRefresh = UserDefaultsValue<Bool>(key: "backgroundRefresh", default: true)