diff --git a/Telegram-iOS/NotificationManager.swift b/Telegram-iOS/NotificationManager.swift index b747dd4be0..97e184a31b 100644 --- a/Telegram-iOS/NotificationManager.swift +++ b/Telegram-iOS/NotificationManager.swift @@ -184,7 +184,7 @@ final class NotificationManager { if #available(iOS 10.0, *) { let content = UNMutableNotificationContent() if isLocked { - content.body = strings.LOCKED_MESSAGE("").0 + content.body = strings.PUSH_LOCKED_MESSAGE("").0 } else { if title.isEmpty { content.body = text @@ -226,7 +226,7 @@ final class NotificationManager { } else { let notification = UILocalNotification() if isLocked { - notification.alertBody = strings.LOCKED_MESSAGE("").0 + notification.alertBody = strings.PUSH_LOCKED_MESSAGE("").0 } else { if #available(iOS 8.2, *) { notification.alertTitle = title @@ -427,11 +427,23 @@ final class NotificationManager { if messages.count > 1 { if messages[0].forwardInfo != nil { if let author = firstMessage.author, displayAuthor { - title = nil - body = strings.CHAT_MESSAGE_FWDS(author.compactDisplayTitle, peer.displayTitle, "\(messages.count)").0 + let rawText = presentationData.strings.PUSH_CHAT_MESSAGE_FWDS(Int32(messages.count), peer.displayTitle, author.compactDisplayTitle, Int32(messages.count)) + if let index = rawText.firstIndex(of: "|") { + title = String(rawText[rawText.startIndex ..< index]) + body = String(rawText[rawText.index(after: index)...]) + } else { + title = nil + body = rawText + } } else { - title = nil - body = strings.MESSAGE_FWDS(peer.displayTitle, "\(messages.count)").0 + let rawText = presentationData.strings.PUSH_MESSAGE_FWDS(Int32(messages.count), peer.displayTitle, Int32(messages.count)) + if let index = rawText.firstIndex(of: "|") { + title = String(rawText[rawText.startIndex ..< index]) + body = String(rawText[rawText.index(after: index)...]) + } else { + title = nil + body = rawText + } } } else if messages[0].groupingKey != nil { var kind = messageContentKind(messages[0], strings: strings, nameDisplayOrder: nameDisplayOrder, accountPeerId: account.peerId).key @@ -457,23 +469,65 @@ final class NotificationManager { if isChannel { switch kind { case .image: - body = strings.CHANNEL_MESSAGE_PHOTOS(peer.compactDisplayTitle, "\(messages.count)").0 + let rawText = presentationData.strings.PUSH_CHANNEL_MESSAGE_PHOTOS(Int32(messages.count), peer.displayTitle, Int32(messages.count)) + if let index = rawText.firstIndex(of: "|") { + title = String(rawText[rawText.startIndex ..< index]) + body = String(rawText[rawText.index(after: index)...]) + } else { + title = nil + body = rawText + } default: - body = strings.CHANNEL_MESSAGES(peer.compactDisplayTitle, "\(messages.count)").0 + let rawText = presentationData.strings.PUSH_CHANNEL_MESSAGES(Int32(messages.count), peer.displayTitle, Int32(messages.count)) + if let index = rawText.firstIndex(of: "|") { + title = String(rawText[rawText.startIndex ..< index]) + body = String(rawText[rawText.index(after: index)...]) + } else { + title = nil + body = rawText + } } } else if isGroup, let author = firstMessage.author { switch kind { case .image: - body = strings.CHAT_MESSAGE_PHOTOS(author.compactDisplayTitle, peer.displayTitle, "\(messages.count)").0 + let rawText = presentationData.strings.PUSH_CHAT_MESSAGE_PHOTOS(Int32(messages.count), peer.displayTitle, author.compactDisplayTitle, Int32(messages.count)) + if let index = rawText.firstIndex(of: "|") { + title = String(rawText[rawText.startIndex ..< index]) + body = String(rawText[rawText.index(after: index)...]) + } else { + title = nil + body = rawText + } default: - body = strings.CHAT_MESSAGES(author.compactDisplayTitle, peer.displayTitle, "\(messages.count)").0 + let rawText = presentationData.strings.PUSH_CHAT_MESSAGES(Int32(messages.count), peer.displayTitle, author.compactDisplayTitle, Int32(messages.count)) + if let index = rawText.firstIndex(of: "|") { + title = String(rawText[rawText.startIndex ..< index]) + body = String(rawText[rawText.index(after: index)...]) + } else { + title = nil + body = rawText + } } } else { switch kind { case .image: - body = strings.MESSAGE_PHOTOS(peer.displayTitle, "\(messages.count)").0 + let rawText = presentationData.strings.PUSH_MESSAGE_PHOTOS(Int32(messages.count), peer.displayTitle, Int32(messages.count)) + if let index = rawText.firstIndex(of: "|") { + title = String(rawText[rawText.startIndex ..< index]) + body = String(rawText[rawText.index(after: index)...]) + } else { + title = nil + body = rawText + } default: - body = strings.MESSAGES(peer.displayTitle, "\(messages.count)").0 + let rawText = presentationData.strings.PUSH_MESSAGES(Int32(messages.count), peer.displayTitle, Int32(messages.count)) + if let index = rawText.firstIndex(of: "|") { + title = String(rawText[rawText.startIndex ..< index]) + body = String(rawText[rawText.index(after: index)...]) + } else { + title = nil + body = rawText + } } } } @@ -526,17 +580,17 @@ final class NotificationManager { if location.liveBroadcastingTimeout != nil { if let chatMainPeer = chatPeer.chatMainPeer { if let user = chatMainPeer as? TelegramUser { - body = strings.MESSAGE_GEOLIVE(user.displayTitle).0 + body = strings.PUSH_MESSAGE_GEOLIVE(user.displayTitle).0 } else if let _ = chatMainPeer as? TelegramGroup, let author = firstMessage.author { - body = strings.MESSAGE_GEOLIVE(author.displayTitle).0 + body = strings.PUSH_MESSAGE_GEOLIVE(author.displayTitle).0 } else if let channel = chatMainPeer as? TelegramChannel { switch channel.info { case .group: if let author = firstMessage.author { - body = strings.MESSAGE_GEOLIVE(author.displayTitle).0 + body = strings.PUSH_MESSAGE_GEOLIVE(author.displayTitle).0 } case .broadcast: - body = strings.CHANNEL_MESSAGE_GEOLIVE(chatMainPeer.displayTitle).0 + body = strings.PUSH_CHANNEL_MESSAGE_GEOLIVE(chatMainPeer.displayTitle).0 } } } @@ -546,14 +600,14 @@ final class NotificationManager { } } } else { - body = strings.ENCRYPTED_MESSAGE("").0 + body = strings.PUSH_ENCRYPTED_MESSAGE("").0 } if isLocked { title = nil } if !displayContents { - body = strings.ENCRYPTED_MESSAGE("").0 + body = strings.PUSH_ENCRYPTED_MESSAGE("").0 } var userInfo: [AnyHashable: Any] = ["peerId": firstMessage.id.peerId.toInt64()] @@ -722,7 +776,7 @@ final class NotificationManager { if let notificationCall = call { if #available(iOS 10.0, *) { let content = UNMutableNotificationContent() - content.body = presentationData.strings.PHONE_CALL_REQUEST(notificationCall.peer?.displayTitle ?? "").0 + content.body = presentationData.strings.PUSH_PHONE_CALL_REQUEST(notificationCall.peer?.displayTitle ?? "").0 content.sound = UNNotificationSound(named: "0.m4a") content.categoryIdentifier = "incomingCall" content.userInfo = [:] @@ -739,7 +793,7 @@ final class NotificationManager { } else { let notification = UILocalNotification() - notification.alertBody = presentationData.strings.PHONE_CALL_REQUEST(notificationCall.peer?.displayTitle ?? "").0 + notification.alertBody = presentationData.strings.PUSH_PHONE_CALL_REQUEST(notificationCall.peer?.displayTitle ?? "").0 notification.category = "incomingCall" notification.userInfo = ["callId": String(describing: notificationCall.internalId)] notification.soundName = "0.m4a" diff --git a/Telegram-iOS/en.lproj/Localizable.strings b/Telegram-iOS/en.lproj/Localizable.strings index 354f701c0e..b7b7978334 100644 --- a/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram-iOS/en.lproj/Localizable.strings @@ -63,7 +63,6 @@ "PUSH_CHANNEL_MESSAGE_GEO" = "%1$@ posted a map"; "PUSH_CHANNEL_MESSAGE_GEOLIVE" = "%1$@ posted a live location"; "PUSH_CHANNEL_MESSAGE_GIF" = "%1$@ posted a GIF"; -"PUSH_CHANNEL_MESSAGE_PHOTOS" = "%1$@ posted %2$@ photos"; "PUSH_CHANNEL_MESSAGES" = "%1$@ posted %2$@ messages"; "PUSH_PINNED_TEXT" = "%1$@ pinned \"%2$@\""; @@ -213,6 +212,10 @@ "PUSH_PHONE_CALL_REQUEST" = "%1$@|is calling you!"; "PUSH_PHONE_CALL_MISSED" = "%1$@|You missed a call"; +"LOCAL_MESSAGE_FWDS" = "%1$@ forwarded you %2$d messages"; +"LOCAL_CHANNEL_MESSAGE_FWDS" = "%1$@ posted %2$d forwarded messages"; +"LOCAL_CHAT_MESSAGE_FWDS" = "%1$@ forwarded %2$d messages"; + // Common "Common.OK" = "OK"; "Common.Cancel" = "Cancel"; diff --git a/submodules/TelegramUI b/submodules/TelegramUI index 4e9b52480d..48cc78e910 160000 --- a/submodules/TelegramUI +++ b/submodules/TelegramUI @@ -1 +1 @@ -Subproject commit 4e9b52480d865a8b04d5393f19b670934c8e6b58 +Subproject commit 48cc78e9105b13889ed440ae800db0ef9dab75b9 diff --git a/tools/GenerateLocalization.swift b/tools/GenerateLocalization.swift index 446ed5bedb..9c86482f2e 100644 --- a/tools/GenerateLocalization.swift +++ b/tools/GenerateLocalization.swift @@ -5,7 +5,7 @@ struct Entry { let value: String } -enum ArgumentType { +enum ArgumentType: Equatable { case any case integer(decimalNumbers: Int) case float @@ -24,7 +24,7 @@ enum ArgumentType { } } -struct Argument { +struct Argument: Equatable { let index: Int let type: ArgumentType } @@ -424,7 +424,69 @@ public final class PresentationStrings { } for (key, id) in pluralizationKeyPairs { - result += + var arguments: [Argument]? + for (otherKey, value, _) in idKeyPairs { + if let (base, _) = pluralizationForm(otherKey), base == key { + let localArguments = parseArguments(value) + if !localArguments.isEmpty { + let numericCount = localArguments.filter({ + switch $0.type { + case .integer: + return true + default: + return false + } + }).count + if numericCount > 1 { + preconditionFailure("value for \(key) contains more than 1 numeric argument") + } + if let argumentsValue = arguments { + for i in 0 ..< min(argumentsValue.count, localArguments.count) { + if argumentsValue[i] != localArguments[i] { + preconditionFailure("value for \(key) contains incompatible argument lists") + } + } + if argumentsValue.count < localArguments.count { + arguments = localArguments + } + } else { + arguments = localArguments + } + } + } + } + if let arguments = arguments, !arguments.isEmpty { + if arguments.count > 1 { + var argList = "" + var argListAccessor = "" + for argument in arguments { + if !argList.isEmpty { + argList.append(", ") + } + if !argListAccessor.isEmpty { + argListAccessor.append(", ") + } + argList.append("_ _\(argument.index): ") + argListAccessor.append("_\(argument.index)") + switch argument.type { + case .any: + argList.append("String") + case .integer: + argList.append("Int32") + case .float: + argList.append("Float") + } + } + result += +""" + public func \(escapedIdentifier(key))(_ selector: Int32, \(argList)) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[\(id) * \(PluralizationForm.formCount) + Int(form.rawValue)]!, \(argListAccessor)) + } + +""" + } else { + result += """ public func \(escapedIdentifier(key))(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) @@ -432,6 +494,10 @@ public final class PresentationStrings { } """ + } + } else { + preconditionFailure("arguments for \(key) is nil") + } } result +=