diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 90e1d0eb5c..c3bab8c3c1 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -15506,3 +15506,31 @@ Error: %8$@"; "Gift.Auction.Extension" = "+ %1$@ for late bids in top %2$@"; "ChatList.Auctions.UpcomingAuction" = "Upcoming Auction"; + +"Login.PhoneWithPasskeySubtitle" = "Enter your phone number\nor [log in using Passkey >](passkey)"; +"PrivacySettings.Passkey" = "Passkey"; +"Attachment.SharedAudio" = "SHARED AUDIO"; +"Attachment.FilesSearchPlaceholder" = "Search shared audio"; +"Chat.GiftPurchaseOffer.Reject" = "Reject"; +"Chat.GiftPurchaseOffer.Accept" = "Accept"; + +"Passkeys.DeleteAlert.Title" = "Delete Passkey?"; +"Passkeys.DeleteAlert.Text" = "Once deleted, this passkey can't be used to log in.\n\nDon't forget to remove it from your password manager too."; +"Passkeys.DeleteAlert.Action" = "Delete"; +"Passkeys.Into.Title" = "Protect your account"; +"Passkeys.Subtitle" = "Log in safely and keep your account secure."; +"Passkeys.Into.Title0" = "Create a Passkey"; +"Passkeys.Into.Text0" = "Make a passkey to sign in easily and safely."; +"Passkeys.Into.Title1" = "Log in with Face ID"; +"Passkeys.Into.Text1" = "Use Face ID, Touch ID, or your passcode to sign in."; +"Passkeys.Into.Title2" = "Store Passkey Securely"; +"Passkeys.Into.Text2" = "Your passkey is safely kept in your iCloud Keychain."; +"Passkeys.ButtonCreate" = "Create Passkey"; +"Passkeys.ButtonSkip" = "Skip"; +"Passkeys.Title" = "Passkeys"; +"Passkeys.Subtitle" = "Log in safely and keep your account secure."; +"Passkeys.EmptyName" = "Passkey"; +"Passkeys.PasskeyCreatedPattern" = "created %@"; +"Passkeys.PasskeyCreatedAndUsedPattern" = "created %1$@ • used %2$@"; +"Passkeys.AddPasskey" = "Create Passkey"; +"Passkeys.ListFooter" = "Your passkeys are stored securely in your password manager."; diff --git a/submodules/AuthorizationUI/Sources/AuthorizationSequencePhoneEntryControllerNode.swift b/submodules/AuthorizationUI/Sources/AuthorizationSequencePhoneEntryControllerNode.swift index 189f8e7c13..69ca7fc799 100644 --- a/submodules/AuthorizationUI/Sources/AuthorizationSequencePhoneEntryControllerNode.swift +++ b/submodules/AuthorizationUI/Sources/AuthorizationSequencePhoneEntryControllerNode.swift @@ -576,11 +576,10 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode { } func updateDisplayPasskeyLoginOption() { - //TODO:localize if self.account == nil { return } - let attributedText = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString("Enter your phone number\nor [log in using Passkey >](passkey)", attributes: MarkdownAttributes( + let attributedText = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(self.strings.Login_PhoneWithPasskeySubtitle, attributes: MarkdownAttributes( body: MarkdownAttributeSet(font: Font.regular(17.0), textColor: self.theme.list.itemPrimaryTextColor), bold: MarkdownAttributeSet(font: Font.semibold(17.0), textColor: self.theme.list.itemPrimaryTextColor), link: MarkdownAttributeSet(font: Font.regular(17.0), textColor: self.theme.list.itemAccentColor), @@ -607,7 +606,7 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode { let titleInset: CGFloat = layout.size.width > 320.0 ? 18.0 : 0.0 let additionalBottomInset: CGFloat = layout.size.width > 320.0 ? 80.0 : 10.0 - self.titleNode.attributedText = NSAttributedString(string: self.account == nil ? strings.Login_NewNumber : strings.Login_PhoneTitle, font: Font.bold(28.0), textColor: self.theme.list.itemPrimaryTextColor) + self.titleNode.attributedText = NSAttributedString(string: self.account == nil ? self.strings.Login_NewNumber : self.strings.Login_PhoneTitle, font: Font.bold(28.0), textColor: self.theme.list.itemPrimaryTextColor) self.titleActivateAreaNode.accessibilityLabel = self.titleNode.attributedText?.string ?? "" let inset: CGFloat = 24.0 diff --git a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift index 755ecdc75d..09aeb82886 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift @@ -673,12 +673,11 @@ private func privacyAndSecurityControllerEntries( entries.append(.twoStepVerification(presentationData.theme, presentationData.strings.PrivacySettings_TwoStepAuth, twoStepAuthString, twoStepAuthData)) if displayPasskeys { - //TODO:localize var passkeysString = "" if let hasPasskeys = hasPasskeys { - passkeysString = hasPasskeys ? "On" : "Off" + passkeysString = hasPasskeys ? presentationData.strings.PrivacySettings_PasscodeOn : presentationData.strings.PrivacySettings_PasscodeOff } - entries.append(.passkeys(presentationData.theme, "Passkey", passkeysString)) + entries.append(.passkeys(presentationData.theme, presentationData.strings.PrivacySettings_Passkey, passkeysString)) } if let privacySettings = privacySettings { diff --git a/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileController.swift b/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileController.swift index e3af2cbb87..59b5b88acf 100644 --- a/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileController.swift +++ b/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileController.swift @@ -207,8 +207,7 @@ private func attachmentFileControllerEntries(presentationData: PresentationData, case .recent: listTitle = presentationData.strings.Attachment_RecentlySentFiles case .audio: - //TODO:localize - listTitle = "SHARED AUDIO" + listTitle = presentationData.strings.Attachment_SharedAudio } if case .audio = mode { diff --git a/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift b/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift index ed7b71bd06..d1b6135765 100644 --- a/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift +++ b/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift @@ -138,7 +138,6 @@ private final class AttachmentFileSearchItemNode: ItemListControllerSearchNode { transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: navigationBarHeight), size: CGSize(width: layout.size.width, height: layout.size.height - navigationBarHeight))) self.containerNode.containerLayoutUpdated(layout.withUpdatedSize(CGSize(width: layout.size.width, height: layout.size.height - navigationBarHeight)), navigationBarHeight: 0.0, transition: transition) - //TODO:localize let searchInputSize = self.searchInput.update( transition: .immediate, component: AnyComponent( @@ -147,7 +146,7 @@ private final class AttachmentFileSearchItemNode: ItemListControllerSearchNode { strings: self.presentationData.strings, metrics: layout.metrics, safeInsets: layout.safeInsets, - placeholder: self.mode == .audio ? "Search shared audio" : self.presentationData.strings.Attachment_FilesSearchPlaceholder, + placeholder: self.mode == .audio ? self.presentationData.strings.Attachment_FilesSearchPlaceholder : self.presentationData.strings.Attachment_FilesSearchPlaceholder, updated: { [weak self] query in guard let self else { return diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift index f15cdb59df..dd71ee1b79 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift @@ -2844,7 +2844,6 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI icon: .suggestedPostApprove ) ] - //TODO:localize let (minWidth, buttonsLayout) = actionButtonsLayout( item.context, item.presentationData.theme, @@ -2854,8 +2853,8 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI ReplyMarkupMessageAttribute( rows: [ ReplyMarkupRow(buttons: [ - ReplyMarkupButton(title: "Reject", titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonDecline)), - ReplyMarkupButton(title: "Accept", titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonApprove)) + ReplyMarkupButton(title: item.presentationData.strings.Chat_GiftPurchaseOffer_Reject, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonDecline)), + ReplyMarkupButton(title: item.presentationData.strings.Chat_GiftPurchaseOffer_Accept, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonApprove)) ]) ], flags: [], diff --git a/submodules/TelegramUI/Components/Settings/PasskeysScreen/Sources/PasskeysScreen.swift b/submodules/TelegramUI/Components/Settings/PasskeysScreen/Sources/PasskeysScreen.swift index 8443d2297e..ba88ee22dc 100644 --- a/submodules/TelegramUI/Components/Settings/PasskeysScreen/Sources/PasskeysScreen.swift +++ b/submodules/TelegramUI/Components/Settings/PasskeysScreen/Sources/PasskeysScreen.swift @@ -180,9 +180,8 @@ final class PasskeysScreenComponent: Component { return } let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }) - //TODO:localize - controller.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: "Delete Passkey?", text: "Once deleted, this passkey can't be used to log in.\n\nDon't forget to remove it from your password manager too.", actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: { - }), TextAlertAction(type: .destructiveAction, title: "Delete", action: { [weak self] in + controller.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: environment.strings.Passkeys_DeleteAlert_Title, text: environment.strings.Passkeys_DeleteAlert_Text, actions: [TextAlertAction(type: .genericAction, title: environment.strings.Common_Cancel, action: { + }), TextAlertAction(type: .destructiveAction, title: environment.strings.Passkeys_DeleteAlert_Action, action: { [weak self] in guard let self else { return } @@ -266,6 +265,7 @@ final class PasskeysScreenComponent: Component { component: AnyComponent(PasskeysScreenIntroComponent( context: component.context, theme: environment.theme, + strings: environment.strings, insets: UIEdgeInsets(top: environment.statusBarHeight + environment.navigationHeight, left: 0.0, bottom: environment.safeInsets.bottom, right: 0.0), displaySkip: component.displaySkip, createPasskeyAction: { [weak self] in diff --git a/submodules/TelegramUI/Components/Settings/PasskeysScreen/Sources/PasskeysScreenIntroComponent.swift b/submodules/TelegramUI/Components/Settings/PasskeysScreen/Sources/PasskeysScreenIntroComponent.swift index 49ef832830..5a63cb70e6 100644 --- a/submodules/TelegramUI/Components/Settings/PasskeysScreen/Sources/PasskeysScreenIntroComponent.swift +++ b/submodules/TelegramUI/Components/Settings/PasskeysScreen/Sources/PasskeysScreenIntroComponent.swift @@ -13,6 +13,7 @@ import BundleIconComponent final class PasskeysScreenIntroComponent: Component { let context: AccountContext let theme: PresentationTheme + let strings: PresentationStrings let insets: UIEdgeInsets let displaySkip: Bool let createPasskeyAction: () -> Void @@ -21,6 +22,7 @@ final class PasskeysScreenIntroComponent: Component { init( context: AccountContext, theme: PresentationTheme, + strings: PresentationStrings, insets: UIEdgeInsets, displaySkip: Bool, createPasskeyAction: @escaping () -> Void, @@ -28,6 +30,7 @@ final class PasskeysScreenIntroComponent: Component { ) { self.context = context self.theme = theme + self.strings = strings self.insets = insets self.displaySkip = displaySkip self.createPasskeyAction = createPasskeyAction @@ -41,6 +44,9 @@ final class PasskeysScreenIntroComponent: Component { if lhs.theme !== rhs.theme { return false } + if lhs.strings !== rhs.strings { + return false + } if lhs.insets != rhs.insets { return false } @@ -120,7 +126,6 @@ final class PasskeysScreenIntroComponent: Component { var contentHeight: CGFloat = 0.0 - //TODO:localize let iconSize = self.icon.update( transition: .immediate, component: AnyComponent(LottieComponent( @@ -145,7 +150,7 @@ final class PasskeysScreenIntroComponent: Component { let titleSize = self.title.update( transition: .immediate, component: AnyComponent(MultilineTextComponent( - text: .plain(NSAttributedString(string: "Protect your account", font: Font.bold(27.0), textColor: component.theme.list.itemPrimaryTextColor)), + text: .plain(NSAttributedString(string: component.strings.Passkeys_Into_Title, font: Font.bold(27.0), textColor: component.theme.list.itemPrimaryTextColor)), horizontalAlignment: .center, maximumNumberOfLines: 0 )), @@ -166,7 +171,7 @@ final class PasskeysScreenIntroComponent: Component { let subtitleSize = self.subtitle.update( transition: .immediate, component: AnyComponent(BalancedTextComponent( - text: .plain(NSAttributedString(string: "Log in safely and keep your account secure.", font: Font.regular(16.0), textColor: component.theme.list.itemPrimaryTextColor)), + text: .plain(NSAttributedString(string: component.strings.Passkeys_Subtitle, font: Font.regular(16.0), textColor: component.theme.list.itemPrimaryTextColor)), horizontalAlignment: .center, maximumNumberOfLines: 0, lineSpacing: 0.2 @@ -193,18 +198,18 @@ final class PasskeysScreenIntroComponent: Component { let itemDescs: [ItemDesc] = [ ItemDesc( icon: "Settings/Passkeys/Intro1", - title: "Create a Passkey", - text: "Make a passkey to sign in easily and safely." + title: component.strings.Passkeys_Into_Title0, + text: component.strings.Passkeys_Into_Text0 ), ItemDesc( icon: "Settings/Passkeys/Intro2", - title: "Log in with Face ID", - text: "Use Face ID, Touch ID, or your passcode to sign in." + title: component.strings.Passkeys_Into_Title1, + text: component.strings.Passkeys_Into_Text1 ), ItemDesc( icon: "Settings/Passkeys/Intro3", - title: "Store Passkey Securely", - text: "Your passkey is safely kept in your iCloud Keychain." + title: component.strings.Passkeys_Into_Title2, + text: component.strings.Passkeys_Into_Text2 ) ] for i in 0 ..< itemDescs.count { @@ -290,7 +295,7 @@ final class PasskeysScreenIntroComponent: Component { ), content: AnyComponentWithIdentity( id: AnyHashable(0), - component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "Create Passkey", font: Font.semibold(17.0), textColor: component.theme.list.itemCheckColors.foregroundColor)))) + component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: component.strings.Passkeys_ButtonCreate, font: Font.semibold(17.0), textColor: component.theme.list.itemCheckColors.foregroundColor)))) ), action: { [weak self] in guard let self, let component = self.component else { @@ -312,7 +317,6 @@ final class PasskeysScreenIntroComponent: Component { skipButton = ComponentView() self.skipButton = skipButton } - //TODO:localize skipButtonSize = skipButton.update( transition: transition, component: AnyComponent(ButtonComponent( @@ -325,7 +329,7 @@ final class PasskeysScreenIntroComponent: Component { ), content: AnyComponentWithIdentity( id: AnyHashable(0), - component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "Skip", font: Font.semibold(17.0), textColor: component.theme.list.itemCheckColors.foregroundColor)))) + component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: component.strings.Passkeys_ButtonSkip, font: Font.semibold(17.0), textColor: component.theme.list.itemCheckColors.foregroundColor)))) ), action: { [weak self] in guard let self, let component = self.component else { diff --git a/submodules/TelegramUI/Components/Settings/PasskeysScreen/Sources/PasskeysScreenListComponent.swift b/submodules/TelegramUI/Components/Settings/PasskeysScreen/Sources/PasskeysScreenListComponent.swift index 862e6600ed..86c5dccc36 100644 --- a/submodules/TelegramUI/Components/Settings/PasskeysScreen/Sources/PasskeysScreenListComponent.swift +++ b/submodules/TelegramUI/Components/Settings/PasskeysScreen/Sources/PasskeysScreenListComponent.swift @@ -123,7 +123,6 @@ final class PasskeysScreenListComponent: Component { contentHeight += component.insets.top contentHeight += 8.0 - //TODO:localize let iconSize = self.icon.update( transition: .immediate, component: AnyComponent(LottieComponent( @@ -148,7 +147,7 @@ final class PasskeysScreenListComponent: Component { let titleSize = self.title.update( transition: .immediate, component: AnyComponent(MultilineTextComponent( - text: .plain(NSAttributedString(string: "Passkeys", font: Font.bold(27.0), textColor: component.theme.list.itemPrimaryTextColor)), + text: .plain(NSAttributedString(string: component.strings.Passkeys_Title, font: Font.bold(27.0), textColor: component.theme.list.itemPrimaryTextColor)), horizontalAlignment: .center, maximumNumberOfLines: 0 )), @@ -169,7 +168,7 @@ final class PasskeysScreenListComponent: Component { let subtitleSize = self.subtitle.update( transition: .immediate, component: AnyComponent(BalancedTextComponent( - text: .plain(NSAttributedString(string: "Log in safely and keep your account secure.", font: Font.regular(16.0), textColor: component.theme.list.itemPrimaryTextColor)), + text: .plain(NSAttributedString(string: component.strings.Passkeys_Subtitle, font: Font.regular(16.0), textColor: component.theme.list.itemPrimaryTextColor)), horizontalAlignment: .center, maximumNumberOfLines: 0, lineSpacing: 0.2 @@ -229,11 +228,12 @@ final class PasskeysScreenListComponent: Component { ) } - //TODO:localize - var subtitleString = "created \(dateString)" + let subtitleString: String if let lastUsageDate = passkey.lastUsageDate { let lastUsedDateString = dateFormatter.string(from: Date(timeIntervalSince1970: Double(lastUsageDate))) - subtitleString.append(" • used \(lastUsedDateString)") + subtitleString = component.strings.Passkeys_PasskeyCreatedAndUsedPattern(dateString, lastUsedDateString).string + } else { + subtitleString = component.strings.Passkeys_PasskeyCreatedPattern(dateString).string } listSectionItems.append(AnyComponentWithIdentity(id: passkey.id, component: AnyComponent(ListActionItemComponent( @@ -241,7 +241,7 @@ final class PasskeysScreenListComponent: Component { title: AnyComponent(VStack([ AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent( text: .plain(NSAttributedString( - string: passkey.name.isEmpty ? "Passkey" : passkey.name, //TODO:localize + string: passkey.name.isEmpty ? component.strings.Passkeys_EmptyName : passkey.name, font: Font.regular(17.0), textColor: component.theme.list.itemPrimaryTextColor )), @@ -283,7 +283,7 @@ final class PasskeysScreenListComponent: Component { title: AnyComponent(VStack([ AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent( text: .plain(NSAttributedString( - string: "Create Passkey", //TODO:localize + string: component.strings.Passkeys_AddPasskey, font: Font.regular(17.0), textColor: component.theme.list.itemAccentColor )), @@ -305,7 +305,6 @@ final class PasskeysScreenListComponent: Component { )))) } - //TODO:localize let listSectionSize = self.listSection.update( transition: transition, component: AnyComponent(ListSectionComponent( @@ -314,7 +313,7 @@ final class PasskeysScreenListComponent: Component { header: nil, footer: AnyComponent(MultilineTextComponent( text: .plain(NSAttributedString( - string: "Your passkeys are stored securely in your password manager.", + string: component.strings.Passkeys_ListFooter, font: Font.regular(13.0), textColor: component.theme.list.freeTextColor )),