diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 0dd370e466..d55edf9f8f 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -11015,7 +11015,7 @@ Sorry for the inconvenience."; "Story.ToastQualitySD.Title" = "Quality Lowered"; "Story.ToastQualitySD.Text" = "Stories will now download faster."; "Story.ToastQualityHD.Title" = "Quality Increased"; -"Story.ToastQualityHD.Text" = "You can lower the quality later for faster downloads." +"Story.ToastQualityHD.Text" = "You can lower the quality later for faster downloads."; "Story.UpgradeQuality.Title" = "High-Quality Stories"; "Story.UpgradeQuality.Text" = "Subscribe to premium to view stories in higher resolution."; @@ -11033,3 +11033,11 @@ Sorry for the inconvenience."; "Chat.TagsHeaderPanel.AddTagsSuffix" = "to your Saved Messages"; "Chat.ReactionContextMenu.SetTagLabel" = "Set Name"; "Chat.ReactionContextMenu.EditTagLabel" = "Edit Name"; + +"Chat.BottomSearchPanel.MessageCountFormat" = "%1$@ %2$@"; +"Chat.BottomSearchPanel.MessageCount_1" = "message"; +"Chat.BottomSearchPanel.MessageCount_any" = "messages"; + +"Chat.BottomSearchPanel.DisplayModeFormat" = "Show as %@"; +"Chat.BottomSearchPanel.DisplayModeChat" = "Chat"; +"Chat.BottomSearchPanel.DisplayModeList" = "List"; diff --git a/build-system/GenerateStrings/GenerateStrings.py b/build-system/GenerateStrings/GenerateStrings.py index be3033ae34..31741133a1 100644 --- a/build-system/GenerateStrings/GenerateStrings.py +++ b/build-system/GenerateStrings/GenerateStrings.py @@ -646,7 +646,9 @@ static NSString * _Nonnull getPluralizedIndirect(_PresentationStrings * _Nonnull if entry.is_pluralized: argument_format_type = '' - if entry.positional_arguments[0].kind == 'd': + if len(entry.positional_arguments) == 0: + argument_format_type = '1' + elif entry.positional_arguments[0].kind == 'd': argument_format_type = '0' elif entry.positional_arguments[0].kind == '@': argument_format_type = '1' diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index d3e0a6624b..63fb56455f 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -11303,7 +11303,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc var items: [ContextMenuItem] = [] - items.append(.action(ContextMenuActionItem(text: strings.Chat.SavedMessagesModeMenu_ViewAsChats, icon: { theme in + items.append(.action(ContextMenuActionItem(text: strings.Chat_SavedMessagesModeMenu_ViewAsChats, icon: { theme in if !isViewingAsTopics { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: .clear) } diff --git a/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift index 92fee5cb18..9f15bc671e 100644 --- a/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift @@ -786,7 +786,7 @@ final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, Chat return } - let promptController = savedTagNameAlertController(context: self.context, updatedPresentationData: nil, text: optionTitle, subtext: presentatinData.strings.Chat_EditTagTitle_Text, value: savedMessageTags.tags.first(where: { $0.reaction == reaction })?.title ?? "", reaction: reaction, file: reactionFile, characterLimit: 10, apply: { [weak self] value in + let promptController = savedTagNameAlertController(context: self.context, updatedPresentationData: nil, text: optionTitle, subtext: presentationData.strings.Chat_EditTagTitle_Text, value: savedMessageTags.tags.first(where: { $0.reaction == reaction })?.title ?? "", reaction: reaction, file: reactionFile, characterLimit: 10, apply: { [weak self] value in guard let self else { return } diff --git a/submodules/TelegramUI/Sources/ChatTagSearchInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTagSearchInputPanelNode.swift index db5571e274..11911f95b9 100644 --- a/submodules/TelegramUI/Sources/ChatTagSearchInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTagSearchInputPanelNode.swift @@ -19,6 +19,27 @@ import AnimatedTextComponent private let labelFont = Font.regular(15.0) +private func extractAnimatedTextString(string: PresentationStrings.FormattedString, id: String, mapping: [Int: AnimatedTextComponent.Item.Content]) -> [AnimatedTextComponent.Item] { + var textItems: [AnimatedTextComponent.Item] = [] + + var previousIndex = 0 + let nsString = string.string as NSString + for range in string.ranges.sorted(by: { $0.range.lowerBound < $1.range.lowerBound }) { + if range.range.lowerBound > previousIndex { + textItems.append(AnimatedTextComponent.Item(id: AnyHashable("\(id)_text_before_\(range.index)"), isUnbreakable: true, content: .text(nsString.substring(with: NSRange(location: previousIndex, length: range.range.lowerBound - previousIndex))))) + } + if let value = mapping[range.index] { + textItems.append(AnimatedTextComponent.Item(id: AnyHashable("\(id)_item_\(range.index)"), content: value)) + } + previousIndex = range.range.upperBound + } + if nsString.length > previousIndex { + textItems.append(AnimatedTextComponent.Item(id: AnyHashable("\(id)_text_end"), isUnbreakable: true, content: .text(nsString.substring(with: NSRange(location: previousIndex, length: nsString.length - previousIndex))))) + } + + return textItems +} + final class ChatTagSearchInputPanelNode: ChatInputPanelNode { private struct Params: Equatable { var width: CGFloat @@ -169,16 +190,23 @@ final class ChatTagSearchInputPanelNode: ChatInputPanelNode { canChangeListMode = true if params.interfaceState.displayHistoryFilterAsList { - //TODO:localize - resultsTextString.append(AnimatedTextComponent.Item(id: AnyHashable("count_n"), content: .number(displayTotalCount, minDigits: 1))) - resultsTextString.append(AnimatedTextComponent.Item(id: AnyHashable("count_message"), isUnbreakable: true, content: .text(displayTotalCount == 1 ? " message" : " messages"))) + resultsTextString = extractAnimatedTextString(string: params.interfaceState.strings.Chat_BottomSearchPanel_MessageCountFormat( + ".", + "." + ), id: "total_count", mapping: [ + 0: .number(displayTotalCount, minDigits: 1), + 1: .text(params.interfaceState.strings.Chat_BottomSearchPanel_MessageCount(Int32(displayTotalCount))) + ]) } else { let adjustedIndex = results.messageIndices.count - 1 - index - //TODO:localize - resultsTextString.append(AnimatedTextComponent.Item(id: AnyHashable("search_n"), content: .number(adjustedIndex + 1, minDigits: 1))) - resultsTextString.append(AnimatedTextComponent.Item(id: AnyHashable("search_of"), isUnbreakable: true, content: .text(" of "))) - resultsTextString.append(AnimatedTextComponent.Item(id: AnyHashable("search_m"), content: .number(displayTotalCount, minDigits: 1))) + resultsTextString = extractAnimatedTextString(string: params.interfaceState.strings.Items_NOfM( + ".", + "." + ), id: "position", mapping: [ + 0: .number(adjustedIndex + 1, minDigits: 1), + 1: .number(displayTotalCount, minDigits: 1) + ]) } } else { canChangeListMode = false @@ -188,9 +216,13 @@ final class ChatTagSearchInputPanelNode: ChatInputPanelNode { } else if let count = self.tagMessageCount?.count { canChangeListMode = count != 0 - //TODO:localize - resultsTextString.append(AnimatedTextComponent.Item(id: AnyHashable("count_n"), content: .number(count, minDigits: 1))) - resultsTextString.append(AnimatedTextComponent.Item(id: AnyHashable("count_message"), isUnbreakable: true, content: .text(count == 1 ? " message" : " messages"))) + resultsTextString = extractAnimatedTextString(string: params.interfaceState.strings.Chat_BottomSearchPanel_MessageCountFormat( + ".", + "." + ), id: "total_count", mapping: [ + 0: .number(count, minDigits: 1), + 1: .text(params.interfaceState.strings.Chat_BottomSearchPanel_MessageCount(Int32(count))) + ]) } else if let context = self.context, case .peer(context.account.peerId) = params.interfaceState.chatLocation { canChangeListMode = true } @@ -203,14 +235,9 @@ final class ChatTagSearchInputPanelNode: ChatInputPanelNode { } var modeButtonTitle: [AnimatedTextComponent.Item] = [] - //TODO:localize - if params.interfaceState.displayHistoryFilterAsList { - modeButtonTitle.append(AnimatedTextComponent.Item(id: AnyHashable("show_as"), isUnbreakable: true, content: .text("Show as "))) - modeButtonTitle.append(AnimatedTextComponent.Item(id: AnyHashable("chat"), isUnbreakable: true, content: .text("Chat"))) - } else { - modeButtonTitle.append(AnimatedTextComponent.Item(id: AnyHashable("show_as"), isUnbreakable: true, content: .text("Show as "))) - modeButtonTitle.append(AnimatedTextComponent.Item(id: AnyHashable("list"), isUnbreakable: true, content: .text("List"))) - } + modeButtonTitle = extractAnimatedTextString(string: params.interfaceState.strings.Chat_BottomSearchPanel_DisplayModeFormat("."), id: "mode", mapping: [ + 0: params.interfaceState.displayHistoryFilterAsList ? .text(params.interfaceState.strings.Chat_BottomSearchPanel_DisplayModeChat) : .text(params.interfaceState.strings.Chat_BottomSearchPanel_DisplayModeList) + ]) let size = CGSize(width: params.width - params.additionalSideInsets.left * 2.0 - params.leftInset * 2.0, height: height)