From 6d4deb56da21b1d484de8d617e908475cbb3d219 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 7 Mar 2023 11:45:01 +0400 Subject: [PATCH] Add chat language recognition logging --- .../Sources/DebugController.swift | 49 +++++++++++-------- .../Sources/ExperimentalUISettings.swift | 10 +++- .../TranslateUI/Sources/ChatTranslation.swift | 15 +++++- 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/submodules/DebugSettingsUI/Sources/DebugController.swift b/submodules/DebugSettingsUI/Sources/DebugController.swift index 7c0b2789ba..fc82b25d61 100644 --- a/submodules/DebugSettingsUI/Sources/DebugController.swift +++ b/submodules/DebugSettingsUI/Sources/DebugController.swift @@ -48,6 +48,7 @@ private enum DebugControllerSection: Int32 { case logs case logging case experiments + case translation case videoExperiments case videoExperiments2 case info @@ -67,12 +68,10 @@ private enum DebugControllerEntry: ItemListNodeEntry { case logToFile(PresentationTheme, Bool) case logToConsole(PresentationTheme, Bool) case redactSensitiveData(PresentationTheme, Bool) - case enableRaiseToSpeak(PresentationTheme, Bool) case keepChatNavigationStack(PresentationTheme, Bool) case skipReadHistory(PresentationTheme, Bool) case crashOnSlowQueries(PresentationTheme, Bool) case clearTips(PresentationTheme) - case resetTranslationStates(PresentationTheme) case resetNotifications case crash(PresentationTheme) case resetData(PresentationTheme) @@ -102,6 +101,8 @@ private enum DebugControllerEntry: ItemListNodeEntry { case disableVideoAspectScaling(Bool) case enableNetworkFramework(Bool) case restorePurchases(PresentationTheme) + case logTranslationRecognition(Bool) + case resetTranslationStates case hostInfo(PresentationTheme, String) case versionInfo(PresentationTheme) @@ -115,10 +116,12 @@ private enum DebugControllerEntry: ItemListNodeEntry { return DebugControllerSection.logs.rawValue case .logToFile, .logToConsole, .redactSensitiveData: return DebugControllerSection.logging.rawValue - case .enableRaiseToSpeak, .keepChatNavigationStack, .skipReadHistory, .crashOnSlowQueries: + case .keepChatNavigationStack, .skipReadHistory, .crashOnSlowQueries: return DebugControllerSection.experiments.rawValue - case .clearTips, .resetTranslationStates, .resetNotifications, .crash, .resetData, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .reindexUnread, .resetCacheIndex, .reindexCache, .resetBiometricsData, .resetWebViewCache, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .playerEmbedding, .playlistPlayback, .enableQuickReactionSwitch, .voiceConference, .experimentalCompatibility, .enableDebugDataDisplay, .acceleratedStickers, .experimentalBackground, .inlineForums, .localTranscription, . enableReactionOverrides, .restorePurchases: + case .clearTips, .resetNotifications, .crash, .resetData, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .reindexUnread, .resetCacheIndex, .reindexCache, .resetBiometricsData, .resetWebViewCache, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .playerEmbedding, .playlistPlayback, .enableQuickReactionSwitch, .voiceConference, .experimentalCompatibility, .enableDebugDataDisplay, .acceleratedStickers, .experimentalBackground, .inlineForums, .localTranscription, .enableReactionOverrides, .restorePurchases: return DebugControllerSection.experiments.rawValue + case .logTranslationRecognition, .resetTranslationStates: + return DebugControllerSection.translation.rawValue case .preferredVideoCodec: return DebugControllerSection.videoExperiments.rawValue case .disableVideoAspectScaling, .enableNetworkFramework: @@ -156,8 +159,6 @@ private enum DebugControllerEntry: ItemListNodeEntry { return 11 case .redactSensitiveData: return 12 - case .enableRaiseToSpeak: - return 13 case .keepChatNavigationStack: return 14 case .skipReadHistory: @@ -166,8 +167,6 @@ private enum DebugControllerEntry: ItemListNodeEntry { return 16 case .clearTips: return 17 - case .resetTranslationStates: - return 18 case .resetNotifications: return 19 case .crash: @@ -212,16 +211,20 @@ private enum DebugControllerEntry: ItemListNodeEntry { return 39 case .restorePurchases: return 40 - case .playerEmbedding: + case .logTranslationRecognition: return 41 - case .playlistPlayback: + case .resetTranslationStates: return 42 - case .enableQuickReactionSwitch: + case .playerEmbedding: return 43 - case .voiceConference: + case .playlistPlayback: return 44 + case .enableQuickReactionSwitch: + return 45 + case .voiceConference: + return 46 case let .preferredVideoCodec(index, _, _, _): - return 45 + index + return 47 + index case .disableVideoAspectScaling: return 100 case .enableNetworkFramework: @@ -903,12 +906,6 @@ private enum DebugControllerEntry: ItemListNodeEntry { $0.withUpdatedRedactSensitiveData(value) }).start() }) - case let .enableRaiseToSpeak(_, value): - return ItemListSwitchItem(presentationData: presentationData, title: "Enable Raise to Speak", value: value, sectionId: self.section, style: .blocks, updated: { value in - let _ = updateMediaInputSettingsInteractively(accountManager: arguments.sharedContext.accountManager, { - $0.withUpdatedEnableRaiseToSpeak(value) - }).start() - }) case let .keepChatNavigationStack(_, value): return ItemListSwitchItem(presentationData: presentationData, title: "Keep Chat Stack", value: value, sectionId: self.section, style: .blocks, updated: { value in let _ = updateExperimentalUISettingsInteractively(accountManager: arguments.sharedContext.accountManager, { settings in @@ -947,6 +944,14 @@ private enum DebugControllerEntry: ItemListNodeEntry { let _ = context.engine.peers.unmarkChatListFeaturedFiltersAsSeen() } }) + case let .logTranslationRecognition(value): + return ItemListSwitchItem(presentationData: presentationData, title: "Log Language Recognition", value: value, sectionId: self.section, style: .blocks, updated: { value in + let _ = updateExperimentalUISettingsInteractively(accountManager: arguments.sharedContext.accountManager, { settings in + var settings = settings + settings.logLanguageRecognition = value + return settings + }).start() + }) case .resetTranslationStates: return ItemListActionItem(presentationData: presentationData, title: "Reset Translation States", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { if let context = arguments.context { @@ -1342,7 +1347,6 @@ private func debugControllerEntries(sharedContext: SharedAccountContext, present entries.append(.redactSensitiveData(presentationData.theme, loggingSettings.redactSensitiveData)) if isMainApp { - entries.append(.enableRaiseToSpeak(presentationData.theme, mediaInputSettings.enableRaiseToSpeak)) entries.append(.keepChatNavigationStack(presentationData.theme, experimentalSettings.keepChatNavigationStack)) #if DEBUG entries.append(.skipReadHistory(presentationData.theme, experimentalSettings.skipReadHistory)) @@ -1351,7 +1355,6 @@ private func debugControllerEntries(sharedContext: SharedAccountContext, present entries.append(.crashOnSlowQueries(presentationData.theme, experimentalSettings.crashOnLongQueries)) if isMainApp { entries.append(.clearTips(presentationData.theme)) - entries.append(.resetTranslationStates(presentationData.theme)) entries.append(.resetNotifications) } entries.append(.crash(presentationData.theme)) @@ -1378,6 +1381,10 @@ private func debugControllerEntries(sharedContext: SharedAccountContext, present entries.append(.enableReactionOverrides(experimentalSettings.enableReactionOverrides)) } entries.append(.restorePurchases(presentationData.theme)) + + entries.append(.logTranslationRecognition(experimentalSettings.logLanguageRecognition)) + entries.append(.resetTranslationStates) + entries.append(.playerEmbedding(experimentalSettings.playerEmbedding)) entries.append(.playlistPlayback(experimentalSettings.playlistPlayback)) entries.append(.enableQuickReactionSwitch(!experimentalSettings.disableQuickReaction)) diff --git a/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift b/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift index 7e61c20f76..db1ace0d6f 100644 --- a/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift +++ b/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift @@ -51,6 +51,7 @@ public struct ExperimentalUISettings: Codable, Equatable { public var disableLanguageRecognition: Bool public var disableImageContentAnalysis: Bool public var disableBackgroundAnimation: Bool + public var logLanguageRecognition: Bool public static var defaultSettings: ExperimentalUISettings { return ExperimentalUISettings( @@ -78,7 +79,8 @@ public struct ExperimentalUISettings: Codable, Equatable { disableQuickReaction: false, disableLanguageRecognition: false, disableImageContentAnalysis: false, - disableBackgroundAnimation: false + disableBackgroundAnimation: false, + logLanguageRecognition: false ) } @@ -107,7 +109,8 @@ public struct ExperimentalUISettings: Codable, Equatable { disableQuickReaction: Bool, disableLanguageRecognition: Bool, disableImageContentAnalysis: Bool, - disableBackgroundAnimation: Bool + disableBackgroundAnimation: Bool, + logLanguageRecognition: Bool ) { self.keepChatNavigationStack = keepChatNavigationStack self.skipReadHistory = skipReadHistory @@ -134,6 +137,7 @@ public struct ExperimentalUISettings: Codable, Equatable { self.disableLanguageRecognition = disableLanguageRecognition self.disableImageContentAnalysis = disableImageContentAnalysis self.disableBackgroundAnimation = disableBackgroundAnimation + self.logLanguageRecognition = logLanguageRecognition } public init(from decoder: Decoder) throws { @@ -164,6 +168,7 @@ public struct ExperimentalUISettings: Codable, Equatable { self.disableLanguageRecognition = try container.decodeIfPresent(Bool.self, forKey: "disableLanguageRecognition") ?? false self.disableImageContentAnalysis = try container.decodeIfPresent(Bool.self, forKey: "disableImageContentAnalysis") ?? false self.disableBackgroundAnimation = try container.decodeIfPresent(Bool.self, forKey: "disableBackgroundAnimation") ?? false + self.logLanguageRecognition = try container.decodeIfPresent(Bool.self, forKey: "logLanguageRecognition") ?? false } public func encode(to encoder: Encoder) throws { @@ -194,6 +199,7 @@ public struct ExperimentalUISettings: Codable, Equatable { try container.encode(self.disableLanguageRecognition, forKey: "disableLanguageRecognition") try container.encode(self.disableImageContentAnalysis, forKey: "disableImageContentAnalysis") try container.encode(self.disableBackgroundAnimation, forKey: "disableBackgroundAnimation") + try container.encode(self.logLanguageRecognition, forKey: "logLanguageRecognition") } } diff --git a/submodules/TranslateUI/Sources/ChatTranslation.swift b/submodules/TranslateUI/Sources/ChatTranslation.swift index f586036edb..6fd7639622 100644 --- a/submodules/TranslateUI/Sources/ChatTranslation.swift +++ b/submodules/TranslateUI/Sources/ChatTranslation.swift @@ -154,6 +154,9 @@ public func chatTranslationState(context: AccountContext, peerId: EnginePeer.Id) if peerId.id == PeerId.Id._internalFromInt64Value(777000) { return .single(nil) } + + let loggingEnabled = context.sharedContext.immediateExperimentalUISettings.logLanguageRecognition + if #available(iOS 12.0, *) { var baseLang = context.sharedContext.currentPresentationData.with { $0 }.strings.baseLanguageCode let rawSuffix = "-raw" @@ -197,6 +200,9 @@ public func chatTranslationState(context: AccountContext, peerId: EnginePeer.Id) |> map { messageHistoryView, _, _ -> ChatTranslationState? in let messages = messageHistoryView.entries.map(\.message) + if loggingEnabled { + Logger.shared.log("ChatTranslation", "Start language recognizing for \(peerId)") + } var fromLangs: [String: Int] = [:] var count = 0 for message in messages { @@ -205,7 +211,7 @@ public func chatTranslationState(context: AccountContext, peerId: EnginePeer.Id) } if message.text.count >= 10 { var text = String(message.text.prefix(256)) - if var entities = message.textEntitiesAttribute?.entities.filter({ $0.type == .Pre || $0.type == .Code }) { + if var entities = message.textEntitiesAttribute?.entities.filter({ [.Pre, .Code, .Url, .Email, .Mention, .Hashtag, .BotCommand].contains($0.type) }) { entities = entities.sorted(by: { $0.range.lowerBound > $1.range.lowerBound }) var ranges: [Range] = [] for entity in entities { @@ -240,6 +246,10 @@ public func chatTranslationState(context: AccountContext, peerId: EnginePeer.Id) let filteredLanguages = hypotheses.filter { supportedTranslationLanguages.contains(normalize($0.key.rawValue)) }.sorted(by: { $0.value > $1.value }) if let language = filteredLanguages.first { let fromLang = normalize(language.key.rawValue) + if loggingEnabled && !["en", "ru"].contains(fromLang) && !dontTranslateLanguages.contains(fromLang) { + Logger.shared.log("ChatTranslation", "\(text)") + Logger.shared.log("ChatTranslation", "Recognized as: \(fromLang), other hypotheses: \(hypotheses.map { $0.key.rawValue }.joined(separator: ",")) ") + } fromLangs[fromLang] = (fromLangs[fromLang] ?? 0) + message.text.count count += 1 } @@ -260,6 +270,9 @@ public func chatTranslationState(context: AccountContext, peerId: EnginePeer.Id) } } let fromLang = mostFrequent?.0 ?? "" + if loggingEnabled { + Logger.shared.log("ChatTranslation", "Ended with: \(fromLang)") + } let state = ChatTranslationState(baseLang: baseLang, fromLang: fromLang, toLang: nil, isEnabled: false) let _ = updateChatTranslationState(engine: context.engine, peerId: peerId, state: state).start() if !dontTranslateLanguages.contains(fromLang) {