diff --git a/Scripts/LintLocalizableStrings.swift b/Scripts/LintLocalizableStrings.swift new file mode 100755 index 000000000..3f0860735 --- /dev/null +++ b/Scripts/LintLocalizableStrings.swift @@ -0,0 +1,251 @@ +#!/usr/bin/xcrun --sdk macosx swift + +// +// ListLocalizableStrings.swift +// Archa +// +// Created by Morgan Pretty on 18/5/20. +// Copyright © 2020 Archa. All rights reserved. +// +// This script is based on https://github.com/ginowu7/CleanSwiftLocalizableExample the main difference +// is canges to the localized usage regex + +import Foundation + +let fileManager = FileManager.default +let currentPath = ( + ProcessInfo.processInfo.environment["PROJECT_DIR"] ?? fileManager.currentDirectoryPath +) + +/// List of files in currentPath - recursive +var pathFiles: [String] = { + guard let enumerator = fileManager.enumerator(atPath: currentPath), let files = enumerator.allObjects as? [String] else { + fatalError("Could not locate files in path directory: \(currentPath)") + } + + return files +}() + + +/// List of localizable files - not including Localizable files in the Pods +var localizableFiles: [String] = { + return pathFiles + .filter { + $0.hasSuffix("Localizable.strings") && + !$0.contains(".app/") && // Exclude Built Localizable.strings files + !$0.contains("Pods") // Exclude Pods + } +}() + + +/// List of executable files +var executableFiles: [String] = { + return pathFiles.filter { + !$0.localizedCaseInsensitiveContains("test") && // Exclude test files + !$0.contains(".app/") && // Exclude Built Localizable.strings files + !$0.contains("Pods") && // Exclude Pods + ( + NSString(string: $0).pathExtension == "swift" || + NSString(string: $0).pathExtension == "m" + ) + } +}() + +/// Reads contents in path +/// +/// - Parameter path: path of file +/// - Returns: content in file +func contents(atPath path: String) -> String { + print("Path: \(path)") + guard let data = fileManager.contents(atPath: path), let content = String(data: data, encoding: .utf8) else { + fatalError("Could not read from path: \(path)") + } + + return content +} + +/// Returns a list of strings that match regex pattern from content +/// +/// - Parameters: +/// - pattern: regex pattern +/// - content: content to match +/// - Returns: list of results +func regexFor(_ pattern: String, content: String) -> [String] { + guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else { + fatalError("Regex not formatted correctly: \(pattern)") + } + + let matches = regex.matches(in: content, options: [], range: NSRange(location: 0, length: content.utf16.count)) + + return matches.map { + guard let range = Range($0.range(at: 0), in: content) else { + fatalError("Incorrect range match") + } + + return String(content[range]) + } +} + +func create() -> [LocalizationStringsFile] { + return localizableFiles.map(LocalizationStringsFile.init(path:)) +} + +/// +/// +/// - Returns: A list of LocalizationCodeFile - contains path of file and all keys in it +func localizedStringsInCode() -> [LocalizationCodeFile] { + return executableFiles.compactMap { + let content = contents(atPath: $0) + // Note: Need to exclude escaped quotation marks from strings + let matchesOld = regexFor("(?<=NSLocalizedString\\()\\s*\"(?!.*?%d)(.*?)\"", content: content) + let matchesNew = regexFor("\"(?!.*?%d)([^(\\\")]*?)\"(?=\\s*)(?=\\.localized)", content: content) + let allMatches = (matchesOld + matchesNew) + + return allMatches.isEmpty ? nil : LocalizationCodeFile(path: $0, keys: Set(allMatches)) + } +} + +/// Throws error if ALL localizable files does not have matching keys +/// +/// - Parameter files: list of localizable files to validate +func validateMatchKeys(_ files: [LocalizationStringsFile]) { + print("------------ Validating keys match in all localizable files ------------") + + guard let base = files.first, files.count > 1 else { return } + + let files = Array(files.dropFirst()) + + files.forEach { + guard let extraKey = Set(base.keys).symmetricDifference($0.keys).first else { return } + let incorrectFile = $0.keys.contains(extraKey) ? $0 : base + printPretty("error: Found extra key: \(extraKey) in file: \(incorrectFile.path)") + } +} + +/// Throws error if localizable files are missing keys +/// +/// - Parameters: +/// - codeFiles: Array of LocalizationCodeFile +/// - localizationFiles: Array of LocalizableStringFiles +func validateMissingKeys(_ codeFiles: [LocalizationCodeFile], localizationFiles: [LocalizationStringsFile]) { + print("------------ Checking for missing keys -----------") + + guard let baseFile = localizationFiles.first else { + fatalError("Could not locate base localization file") + } + + let baseKeys = Set(baseFile.keys) + + codeFiles.forEach { + let extraKeys = $0.keys.subtracting(baseKeys) + if !extraKeys.isEmpty { + printPretty("error: Found keys in code missing in strings file: \(extraKeys) from \($0.path)") + } + } +} + +/// Throws warning if keys exist in localizable file but are not being used +/// +/// - Parameters: +/// - codeFiles: Array of LocalizationCodeFile +/// - localizationFiles: Array of LocalizableStringFiles +func validateDeadKeys(_ codeFiles: [LocalizationCodeFile], localizationFiles: [LocalizationStringsFile]) { + print("------------ Checking for any dead keys in localizable file -----------") + + guard let baseFile = localizationFiles.first else { + fatalError("Could not locate base localization file") + } + + let baseKeys: Set = Set(baseFile.keys) + let allCodeFileKeys: [String] = codeFiles.flatMap { $0.keys } + let deadKeys: [String] = Array(baseKeys.subtracting(allCodeFileKeys)) + .sorted() + .map { $0.trimmingCharacters(in: CharacterSet(charactersIn: "\"")) } + + if !deadKeys.isEmpty { + printPretty("warning: \(deadKeys) - Suggest cleaning dead keys") + } +} + +protocol Pathable { + var path: String { get } +} + +struct LocalizationStringsFile: Pathable { + let path: String + let kv: [String: String] + + var keys: [String] { + return Array(kv.keys) + } + + init(path: String) { + self.path = path + self.kv = ContentParser.parse(path) + } + + /// Writes back to localizable file with sorted keys and removed whitespaces and new lines + func cleanWrite() { + print("------------ Sort and remove whitespaces: \(path) ------------") + let content = kv.keys.sorted().map { "\($0) = \(kv[$0]!);" }.joined(separator: "\n") + try! content.write(toFile: path, atomically: true, encoding: .utf8) + } + +} + +struct LocalizationCodeFile: Pathable { + let path: String + let keys: Set +} + +struct ContentParser { + + /// Parses contents of a file to localizable keys and values - Throws error if localizable file have duplicated keys + /// + /// - Parameter path: Localizable file paths + /// - Returns: localizable key and value for content at path + static func parse(_ path: String) -> [String: String] { + print("------------ Checking for duplicate keys: \(path) ------------") + + let content = contents(atPath: path) + let trimmed = content + .replacingOccurrences(of: "\n+", with: "", options: .regularExpression, range: nil) + .trimmingCharacters(in: .whitespacesAndNewlines) + let keys = regexFor("\"([^\"]*?)\"(?= =)", content: trimmed) + let values = regexFor("(?<== )\"(.*?)\"(?=;)", content: trimmed) + + if keys.count != values.count { + fatalError("Error parsing contents: Make sure all keys and values are in correct format (this could be due to extra spaces between keys and values)") + } + + return zip(keys, values).reduce(into: [String: String]()) { results, keyValue in + if results[keyValue.0] != nil { + printPretty("error: Found duplicate key: \(keyValue.0) in file: \(path)") + abort() + } + results[keyValue.0] = keyValue.1 + } + } +} + +func printPretty(_ string: String) { + print(string.replacingOccurrences(of: "\\", with: "")) +} + +let stringFiles = create() + +if !stringFiles.isEmpty { + print("------------ Found \(stringFiles.count) file(s) ------------") + + stringFiles.forEach { print($0.path) } + validateMatchKeys(stringFiles) + + // Note: Uncomment the below file to clean out all comments from the localizable file (we don't want this because comments make it readable...) + // stringFiles.forEach { $0.cleanWrite() } + + let codeFiles = localizedStringsInCode() + validateMissingKeys(codeFiles, localizationFiles: stringFiles) + validateDeadKeys(codeFiles, localizationFiles: stringFiles) +} + +print("------------ SUCCESS ------------") diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index c6c3c63e1..4ed98f633 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -781,6 +781,7 @@ FDD250702837199200198BDA /* GarbageCollectionJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD2506F2837199200198BDA /* GarbageCollectionJob.swift */; }; FDD250722837234B00198BDA /* MediaGalleryNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD250712837234B00198BDA /* MediaGalleryNavigationController.swift */; }; FDE72118286C156E0093DF33 /* ChatSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDE72117286C156E0093DF33 /* ChatSettingsViewController.swift */; }; + FDE72154287FE4470093DF33 /* HighlightMentionBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDE72153287FE4470093DF33 /* HighlightMentionBackgroundView.swift */; }; FDE77F6B280FEB28002CFC5D /* ControlMessageProcessRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDE77F6A280FEB28002CFC5D /* ControlMessageProcessRecord.swift */; }; FDED2E3C282E1B5D00B2CD2A /* UICollectionView+ReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDED2E3B282E1B5D00B2CD2A /* UICollectionView+ReusableView.swift */; }; FDF0B73C27FFD3D6004C14C5 /* LinkPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B73B27FFD3D6004C14C5 /* LinkPreview.swift */; }; @@ -1811,6 +1812,9 @@ FDD2506F2837199200198BDA /* GarbageCollectionJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GarbageCollectionJob.swift; sourceTree = ""; }; FDD250712837234B00198BDA /* MediaGalleryNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaGalleryNavigationController.swift; sourceTree = ""; }; FDE72117286C156E0093DF33 /* ChatSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatSettingsViewController.swift; sourceTree = ""; }; + FDE7214F287E50D50093DF33 /* ProtoWrappers.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = ProtoWrappers.py; sourceTree = ""; }; + FDE72150287E50D50093DF33 /* LintLocalizableStrings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LintLocalizableStrings.swift; sourceTree = ""; }; + FDE72153287FE4470093DF33 /* HighlightMentionBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HighlightMentionBackgroundView.swift; sourceTree = ""; }; FDE77F68280F9EDA002CFC5D /* JobRunnerError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JobRunnerError.swift; sourceTree = ""; }; FDE77F6A280FEB28002CFC5D /* ControlMessageProcessRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlMessageProcessRecord.swift; sourceTree = ""; }; FDED2E3B282E1B5D00B2CD2A /* UICollectionView+ReusableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UICollectionView+ReusableView.swift"; sourceTree = ""; }; @@ -2436,6 +2440,7 @@ 4C4AEC4420EC343B0020E72B /* DismissableTextField.swift */, 45E5A6981F61E6DD001E4A8A /* MarqueeLabel.swift */, 34386A53207D271C009F5D9C /* NeverClearView.swift */, + FDE72153287FE4470093DF33 /* HighlightMentionBackgroundView.swift */, 34F308A01ECB469700BB7697 /* OWSBezierPathView.h */, 34F308A11ECB469700BB7697 /* OWSBezierPathView.m */, 34330AA11E79686200DF2FB9 /* OWSProgressView.h */, @@ -3306,6 +3311,7 @@ FD83B9BC27CF2215005E1583 /* SharedTest */, FDC4388F27B9FFC700C60D73 /* SessionMessagingKitTests */, FD83B9B027CF200A005E1583 /* SessionUtilitiesKitTests */, + FDE7214E287E50D50093DF33 /* Scripts */, D221A08C169C9E5E00537ABF /* Frameworks */, D221A08A169C9E5E00537ABF /* Products */, 2BADBA206E0B8D297E313FBA /* Pods */, @@ -3871,6 +3877,15 @@ path = Utilities; sourceTree = ""; }; + FDE7214E287E50D50093DF33 /* Scripts */ = { + isa = PBXGroup; + children = ( + FDE7214F287E50D50093DF33 /* ProtoWrappers.py */, + FDE72150287E50D50093DF33 /* LintLocalizableStrings.swift */, + ); + path = Scripts; + sourceTree = ""; + }; FDF0B7452804F0A8004C14C5 /* Types */ = { isa = PBXGroup; children = ( @@ -4141,6 +4156,7 @@ buildConfigurationList = D221A0BC169C9E5F00537ABF /* Build configuration list for PBXNativeTarget "Session" */; buildPhases = ( 0401967CF3320CC84B175A3B /* [CP] Check Pods Manifest.lock */, + FDE7214D287E50820093DF33 /* Lint Localizable.strings */, D221A085169C9E5E00537ABF /* Sources */, D221A086169C9E5E00537ABF /* Frameworks */, D221A087169C9E5E00537ABF /* Resources */, @@ -4768,6 +4784,25 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + FDE7214D287E50820093DF33 /* Lint Localizable.strings */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Lint Localizable.strings"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Scripts/LintLocalizableStrings.swift\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -5261,6 +5296,7 @@ 7B1581E6271FD2A100848B49 /* VideoPreviewVC.swift in Sources */, B83F2B88240CB75A000A54AB /* UIImage+Scaling.swift in Sources */, 3430FE181F7751D4000EC51B /* GiphyAPI.swift in Sources */, + FDE72154287FE4470093DF33 /* HighlightMentionBackgroundView.swift in Sources */, 340FC8AA204DAC8D007AEB0F /* NotificationSettingsViewController.m in Sources */, 4C090A1B210FD9C7001FD7F9 /* HapticFeedback.swift in Sources */, 34F308A21ECB469700BB7697 /* OWSBezierPathView.m in Sources */, diff --git a/Session/Calls/Call Management/SessionCallManager.swift b/Session/Calls/Call Management/SessionCallManager.swift index b21d98f13..30dbcdfa0 100644 --- a/Session/Calls/Call Management/SessionCallManager.swift +++ b/Session/Calls/Call Management/SessionCallManager.swift @@ -40,8 +40,7 @@ public final class SessionCallManager: NSObject, CallManagerProtocol { } static func buildProviderConfiguration(useSystemCallLog: Bool) -> CXProviderConfiguration { - let localizedName = NSLocalizedString("APPLICATION_NAME", comment: "Name of application") - let providerConfiguration = CXProviderConfiguration(localizedName: localizedName) + let providerConfiguration = CXProviderConfiguration(localizedName: "Session") providerConfiguration.supportsVideo = true providerConfiguration.maximumCallGroups = 1 providerConfiguration.maximumCallsPerCallGroup = 1 diff --git a/Session/Conversations/ConversationViewModel.swift b/Session/Conversations/ConversationViewModel.swift index 4ab71302e..4cc9d64a7 100644 --- a/Session/Conversations/ConversationViewModel.swift +++ b/Session/Conversations/ConversationViewModel.swift @@ -86,7 +86,10 @@ public class ConversationViewModel: OWSAudioPlayerDelegate { // also want to skip the initial query and trigger it async so that the push animation // doesn't stutter (it should load basically immediately but without this there is a // distinct stutter) - self.pagedDataObserver = self.setupPagedObserver(for: threadId) + self.pagedDataObserver = self.setupPagedObserver( + for: threadId, + userPublicKey: getUserHexEncodedPublicKey() + ) // Run the initial query on a background thread so we don't block the push transition DispatchQueue.global(qos: .default).async { [weak self] in @@ -164,7 +167,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate { } } - private func setupPagedObserver(for threadId: String) -> PagedDatabaseObserver { + private func setupPagedObserver(for threadId: String, userPublicKey: String) -> PagedDatabaseObserver { return PagedDatabaseObserver( pagedTable: Interaction.self, pageSize: ConversationViewModel.pageSize, @@ -201,6 +204,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate { groupSQL: MessageViewModel.groupSQL, orderSQL: MessageViewModel.orderSQL, dataQuery: MessageViewModel.baseQuery( + userPublicKey: userPublicKey, orderSQL: MessageViewModel.orderSQL, groupSQL: MessageViewModel.groupSQL ), @@ -316,7 +320,8 @@ public class ConversationViewModel: OWSAudioPlayerDelegate { // it's the last element in the 'sortedData' array index == (sortedData.count - 1) && pageInfo.pageOffset == 0 - ) + ), + currentUserBlindedPublicKey: threadData.currentUserBlindedPublicKey ) } .appending(typingIndicator) @@ -491,7 +496,10 @@ public class ConversationViewModel: OWSAudioPlayerDelegate { self.threadId = updatedThreadId self.observableThreadData = self.setupObservableThreadData(for: updatedThreadId) - self.pagedDataObserver = self.setupPagedObserver(for: updatedThreadId) + self.pagedDataObserver = self.setupPagedObserver( + for: updatedThreadId, + userPublicKey: getUserHexEncodedPublicKey() + ) // Try load everything up to the initial visible message, fallback to just the initial page of messages // if we don't have one diff --git a/Session/Conversations/Input View/InputView.swift b/Session/Conversations/Input View/InputView.swift index a61783967..474c4d6db 100644 --- a/Session/Conversations/Input View/InputView.swift +++ b/Session/Conversations/Input View/InputView.swift @@ -228,6 +228,8 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M authorId: quoteDraftInfo.model.authorId, quotedText: quoteDraftInfo.model.body, threadVariant: threadVariant, + currentUserPublicKey: nil, + currentUserBlindedPublicKey: nil, direction: (quoteDraftInfo.isOutgoing ? .outgoing : .incoming), attachment: quoteDraftInfo.model.attachment, hInset: hInset, diff --git a/Session/Conversations/Message Cells/Content Views/QuoteView.swift b/Session/Conversations/Message Cells/Content Views/QuoteView.swift index 16b91f6ca..2a47a91d9 100644 --- a/Session/Conversations/Message Cells/Content Views/QuoteView.swift +++ b/Session/Conversations/Message Cells/Content Views/QuoteView.swift @@ -28,6 +28,8 @@ final class QuoteView: UIView { authorId: String, quotedText: String?, threadVariant: SessionThread.Variant, + currentUserPublicKey: String?, + currentUserBlindedPublicKey: String?, direction: Direction, attachment: Attachment?, hInset: CGFloat, @@ -43,6 +45,8 @@ final class QuoteView: UIView { authorId: authorId, quotedText: quotedText, threadVariant: threadVariant, + currentUserPublicKey: currentUserPublicKey, + currentUserBlindedPublicKey: currentUserBlindedPublicKey, direction: direction, attachment: attachment, hInset: hInset, @@ -63,6 +67,8 @@ final class QuoteView: UIView { authorId: String, quotedText: String?, threadVariant: SessionThread.Variant, + currentUserPublicKey: String?, + currentUserBlindedPublicKey: String?, direction: Direction, attachment: Attachment?, hInset: CGFloat, @@ -190,6 +196,8 @@ final class QuoteView: UIView { MentionUtilities.highlightMentions( in: $0, threadVariant: threadVariant, + currentUserPublicKey: currentUserPublicKey, + currentUserBlindedPublicKey: currentUserBlindedPublicKey, isOutgoingMessage: isOutgoing, attributes: [:] ) @@ -207,11 +215,21 @@ final class QuoteView: UIView { // Label stack view var authorLabelHeight: CGFloat? if threadVariant == .openGroup || threadVariant == .closedGroup { + let isCurrentUser: Bool = [ + currentUserPublicKey, + currentUserBlindedPublicKey, + ] + .compactMap { $0 } + .asSet() + .contains(authorId) let authorLabel = UILabel() authorLabel.lineBreakMode = .byTruncatingTail - authorLabel.text = Profile.displayName( - id: authorId, - threadVariant: threadVariant + authorLabel.text = (isCurrentUser ? + "MEDIA_GALLERY_SENDER_NAME_YOU".localized() : + Profile.displayName( + id: authorId, + threadVariant: threadVariant + ) ) authorLabel.textColor = textColor authorLabel.font = .boldSystemFont(ofSize: Values.smallFontSize) diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index 248ee419a..ccb099d8e 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -459,6 +459,8 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel authorId: quote.authorId, quotedText: quote.body, threadVariant: cellViewModel.threadVariant, + currentUserPublicKey: cellViewModel.currentUserPublicKey, + currentUserBlindedPublicKey: cellViewModel.currentUserBlindedPublicKey, direction: (cellViewModel.variant == .standardOutgoing ? .outgoing : .incoming @@ -956,6 +958,8 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel attributedString: MentionUtilities.highlightMentions( in: (cellViewModel.body ?? ""), threadVariant: cellViewModel.threadVariant, + currentUserPublicKey: cellViewModel.currentUserPublicKey, + currentUserBlindedPublicKey: cellViewModel.currentUserBlindedPublicKey, isOutgoingMessage: isOutgoing, attributes: [ .foregroundColor : textColor, diff --git a/Session/Conversations/Views & Modals/BodyTextView.swift b/Session/Conversations/Views & Modals/BodyTextView.swift index d329bd972..358333594 100644 --- a/Session/Conversations/Views & Modals/BodyTextView.swift +++ b/Session/Conversations/Views & Modals/BodyTextView.swift @@ -9,10 +9,29 @@ import UIKit // • The long press interaction that shows the context menu should still work final class BodyTextView: UITextView { private let snDelegate: BodyTextViewDelegate? + private let highlightedMentionBackgroundView: HighlightMentionBackgroundView = HighlightMentionBackgroundView() + + override var attributedText: NSAttributedString! { + didSet { + guard attributedText != nil else { return } + + highlightedMentionBackgroundView.maxPadding = highlightedMentionBackgroundView + .calculateMaxPadding(for: attributedText) + highlightedMentionBackgroundView.frame = self.bounds.insetBy( + dx: -highlightedMentionBackgroundView.maxPadding, + dy: -highlightedMentionBackgroundView.maxPadding + ) + } + } init(snDelegate: BodyTextViewDelegate?) { self.snDelegate = snDelegate + super.init(frame: CGRect.zero, textContainer: nil) + + self.clipsToBounds = false // Needed for the 'HighlightMentionBackgroundView' + addSubview(highlightedMentionBackgroundView) + setUpGestureRecognizers() } @@ -39,6 +58,15 @@ final class BodyTextView: UITextView { @objc private func handleDoubleTap() { // Do nothing } + + override func layoutSubviews() { + super.layoutSubviews() + + highlightedMentionBackgroundView.frame = self.bounds.insetBy( + dx: -highlightedMentionBackgroundView.maxPadding, + dy: -highlightedMentionBackgroundView.maxPadding + ) + } } protocol BodyTextViewDelegate { diff --git a/Session/Home/HomeViewModel.swift b/Session/Home/HomeViewModel.swift index 72505ee99..a6c99443b 100644 --- a/Session/Home/HomeViewModel.swift +++ b/Session/Home/HomeViewModel.swift @@ -252,6 +252,11 @@ public class HomeViewModel { 0 : self.state.unreadMessageRequestThreadCount ) + let groupedOldData: [String: [SessionThreadViewModel]] = (self.threadData + .first(where: { $0.model == .threads })? + .elements) + .defaulting(to: []) + .grouped(by: \.threadId) return [ // If there are no unread message requests then hide the message request banner @@ -275,6 +280,13 @@ public class HomeViewModel { return lhs.lastInteractionDate > rhs.lastInteractionDate } + .map { viewModel -> SessionThreadViewModel in + viewModel.populatingCurrentUserBlindedKey( + currentUserBlindedPublicKeyForThisThread: groupedOldData[viewModel.threadId]? + .first? + .currentUserBlindedPublicKey + ) + } ) ], (!data.isEmpty && (pageInfo.pageOffset + pageInfo.currentCount) < pageInfo.totalCount ? diff --git a/Session/Home/Message Requests/MessageRequestsViewModel.swift b/Session/Home/Message Requests/MessageRequestsViewModel.swift index 96a7c69ad..c19ff8538 100644 --- a/Session/Home/Message Requests/MessageRequestsViewModel.swift +++ b/Session/Home/Message Requests/MessageRequestsViewModel.swift @@ -140,12 +140,25 @@ public class MessageRequestsViewModel { } private func process(data: [SessionThreadViewModel], for pageInfo: PagedData.PageInfo) -> [SectionModel] { + let groupedOldData: [String: [SessionThreadViewModel]] = (self.threadData + .first(where: { $0.model == .threads })? + .elements) + .defaulting(to: []) + .grouped(by: \.threadId) + return [ [ SectionModel( section: .threads, elements: data .sorted { lhs, rhs -> Bool in lhs.lastInteractionDate > rhs.lastInteractionDate } + .map { viewModel -> SessionThreadViewModel in + viewModel.populatingCurrentUserBlindedKey( + currentUserBlindedPublicKeyForThisThread: groupedOldData[viewModel.threadId]? + .first? + .currentUserBlindedPublicKey + ) + } ) ], (!data.isEmpty && (pageInfo.pageOffset + pageInfo.currentCount) < pageInfo.totalCount ? diff --git a/Session/Media Viewing & Editing/GIFs/GifPickerViewController.swift b/Session/Media Viewing & Editing/GIFs/GifPickerViewController.swift index 980e985c6..ce215af26 100644 --- a/Session/Media Viewing & Editing/GIFs/GifPickerViewController.swift +++ b/Session/Media Viewing & Editing/GIFs/GifPickerViewController.swift @@ -105,7 +105,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect // Loki: Customize title let titleLabel = UILabel() - titleLabel.text = NSLocalizedString("GIF", comment: "") + titleLabel.text = "accessibility_gif_button".localized().uppercased() titleLabel.textColor = Colors.text titleLabel.font = .boldSystemFont(ofSize: Values.veryLargeFontSize) navigationItem.titleView = titleLabel diff --git a/Session/Meta/Translations/de.lproj/Localizable.strings b/Session/Meta/Translations/de.lproj/Localizable.strings index 764cc21f7..0138af276 100644 --- a/Session/Meta/Translations/de.lproj/Localizable.strings +++ b/Session/Meta/Translations/de.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Kamera"; "accessibility_main_button_collapse" = "Optionen für Anhänge einklappen"; "invalid_recovery_phrase" = "Ungültige Wiederherstellungsphrase"; -"invalid_recovery_phrase" = "Ungültige Wiederherstellungsphrase"; "DISMISS_BUTTON_TEXT" = "Verwerfen"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Einstellungen"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Fehler"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentifizierung gescheitert."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Zu viele gescheiterte Authentifizierungsversuche. Bitte versuche es später erneut."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Du musst einen Passcode in deinen iOS-Einstellungen festlegen, um die Bildschirmsperre zu verwenden."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Du musst einen Passcode in deinen iOS-Einstellungen festlegen, um die Bildschirmsperre zu verwenden."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Du musst einen Passcode in deinen iOS-Einstellungen festlegen, um die Bildschirmsperre zu verwenden."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/en.lproj/Localizable.strings b/Session/Meta/Translations/en.lproj/Localizable.strings index bbdfe3f4e..18d73b302 100644 --- a/Session/Meta/Translations/en.lproj/Localizable.strings +++ b/Session/Meta/Translations/en.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Camera"; "accessibility_main_button_collapse" = "Collapse attachment options"; "invalid_recovery_phrase" = "Invalid Recovery Phrase"; -"invalid_recovery_phrase" = "Invalid Recovery Phrase"; "DISMISS_BUTTON_TEXT" = "Dismiss"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Settings"; @@ -653,11 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Error"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; - +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication failed."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Too many failed authentication attempts. Please try again later."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "You must enable a passcode in your iOS Settings in order to use Screen Lock."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "You must enable a passcode in your iOS Settings in order to use Screen Lock."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "You must enable a passcode in your iOS Settings in order to use Screen Lock."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/es.lproj/Localizable.strings b/Session/Meta/Translations/es.lproj/Localizable.strings index 6a4ca17e0..76abb2b87 100644 --- a/Session/Meta/Translations/es.lproj/Localizable.strings +++ b/Session/Meta/Translations/es.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Cámara"; "accessibility_main_button_collapse" = "Collapse attachment options"; "invalid_recovery_phrase" = "Frase de Recuperación Incorrecta"; -"invalid_recovery_phrase" = "Invalid Recovery Phrase"; "DISMISS_BUTTON_TEXT" = "Descartar"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Ajustes"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Fallo"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Fallo en la identificación."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Demasiados intentos fallidos. Prueda de nuevo más tarde."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Necesitas configurar un código en «Ajustes» de iOS para poder usar el bloqueo de acceso."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Necesitas configurar un código en «Ajustes» de iOS para poder usar el bloqueo de acceso."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Necesitas configurar un código en «Ajustes» de iOS para poder usar el bloqueo de acceso."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/fa.lproj/Localizable.strings b/Session/Meta/Translations/fa.lproj/Localizable.strings index f742bc0bc..60d6d71ee 100644 --- a/Session/Meta/Translations/fa.lproj/Localizable.strings +++ b/Session/Meta/Translations/fa.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Camera"; "accessibility_main_button_collapse" = "Collapse attachment options"; "invalid_recovery_phrase" = "Invalid Recovery Phrase"; -"invalid_recovery_phrase" = "Invalid Recovery Phrase"; "DISMISS_BUTTON_TEXT" = "Dismiss"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Settings"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "خطاء"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "احراز هویت ناموفق بود."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "چندین احراز هویت ناموفق رخ داد. لطفا بعدا تلاش کنید."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "برای استفاده از قفل صفحه نمایش می بایستی یک رمزعبور از تنظیمات iOS خود فعال کنید."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "شما برای استفاده از قفل صفحه نمایس می بایستی یک رمزعبور از تنظیمات iOS خود فعال کنید."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "برای استفاده از قفل صفحه نمایش می بایستی یک رمزعبور از تنظیمات iOS فعال کنید."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/fi.lproj/Localizable.strings b/Session/Meta/Translations/fi.lproj/Localizable.strings index e8e512296..47b43d082 100644 --- a/Session/Meta/Translations/fi.lproj/Localizable.strings +++ b/Session/Meta/Translations/fi.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Kamera"; "accessibility_main_button_collapse" = "Tiivistä liiteasetukset"; "invalid_recovery_phrase" = "Virheellinen Palautuslauseke"; -"invalid_recovery_phrase" = "Virheellinen palautuslauseke"; "DISMISS_BUTTON_TEXT" = "Hylkää"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Asetukset"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Error"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Tunnistautuminen epäonnistui"; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Liian monta epäonnistunutta tunnistautumista. Yritä myöhemmin uudelleen."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Aseta pääsykoodi puhelimesi asetuksista, jotta voit käyttää näytön lukitusta."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Aseta pääsykoodi puhelimesi asetuksista, jotta voit käyttää näytön lukitusta."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Aseta pääsykoodi puhelimesi asetuksista, jotta voit käyttää näytön lukitusta."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/fr.lproj/Localizable.strings b/Session/Meta/Translations/fr.lproj/Localizable.strings index 729b1a90d..ee7ccbf84 100644 --- a/Session/Meta/Translations/fr.lproj/Localizable.strings +++ b/Session/Meta/Translations/fr.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Caméra"; "accessibility_main_button_collapse" = "Réduire les options de pièces jointes"; "invalid_recovery_phrase" = "Phrase de récupération incorrecte"; -"invalid_recovery_phrase" = "Phrase de récupération incorrecte"; "DISMISS_BUTTON_TEXT" = "Fermer"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Paramètres"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "Vous pouvez activer la permission \"Appels vocaux et vidéo\" dans les paramètres de confidentialité."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Erreur"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Échec d’authentification"; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Trop d’essais infructueux d’authentification. Veuillez réessayer plus tard."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Vous devez activer un code dans vos réglages iOS pour utiliser le verrou d’écran."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Vous devez activer un code dans vos réglages iOS pour utiliser le verrou d’écran."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Vous devez activer un code dans vos réglages iOS pour utiliser le verrou d’écran."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/hi.lproj/Localizable.strings b/Session/Meta/Translations/hi.lproj/Localizable.strings index d9589c6a4..86a98157a 100644 --- a/Session/Meta/Translations/hi.lproj/Localizable.strings +++ b/Session/Meta/Translations/hi.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Camera"; "accessibility_main_button_collapse" = "Collapse attachment options"; "invalid_recovery_phrase" = "Invalid Recovery Phrase"; -"invalid_recovery_phrase" = "Invalid Recovery Phrase"; "DISMISS_BUTTON_TEXT" = "Dismiss"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Settings"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Error"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "प्रमाणीकरण असफल"; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "बहुत सारी असफल प्रमाणीकरण की कोशिशें हुई हैं। कृपया थोङी देर बाद कोशिश करें।"; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "सक्रीन लॉक इस्तेमाल करने के लिये अपने iOS सेटिंग्स से पासकोड की अनुमति दें।"; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "सक्रीन लॉक इस्तेमाल करने के लिये अपने iOS सेटिंग्स से पासकोड की अनुमति दें।"; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "सक्रीन लॉक इस्तेमाल करने के लिये अपने iOS सेटिंग्स से पासकोड की अनुमति दें।"; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/hr.lproj/Localizable.strings b/Session/Meta/Translations/hr.lproj/Localizable.strings index 2aaa1e710..4b4b3f6ca 100644 --- a/Session/Meta/Translations/hr.lproj/Localizable.strings +++ b/Session/Meta/Translations/hr.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Kamera"; "accessibility_main_button_collapse" = "Sažmi opcije privitka"; "invalid_recovery_phrase" = "Nevažeća fraza za oporavak"; -"invalid_recovery_phrase" = "Nevažeća fraza za oporavak"; "DISMISS_BUTTON_TEXT" = "Odbaci"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Postavke"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Error"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Provjera autentičnosti nije uspjela."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Previše neuspjelih pokušaja provjere autentičnosti. Pokušajte ponovo kasnije."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Kako biste koristili Zaključavanje zaslona, morate omogućiti lozinku u postavkama iOS-a."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Kako biste koristili Zaključavanje zaslona, morate omogućiti lozinku u postavkama iOS-a."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Kako biste koristili Zaključavanje zaslona, morate omogućiti lozinku u postavkama iOS-a."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/id-ID.lproj/Localizable.strings b/Session/Meta/Translations/id-ID.lproj/Localizable.strings index 227258661..b1376c4db 100644 --- a/Session/Meta/Translations/id-ID.lproj/Localizable.strings +++ b/Session/Meta/Translations/id-ID.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Camera"; "accessibility_main_button_collapse" = "Collapse attachment options"; "invalid_recovery_phrase" = "Invalid Recovery Phrase"; -"invalid_recovery_phrase" = "Invalid Recovery Phrase"; "DISMISS_BUTTON_TEXT" = "Dismiss"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Settings"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Galat"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication failed."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Too many failed authentication attempts. Please try again later."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "You must enable a passcode in your iOS Settings in order to use Screen Lock."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "You must enable a passcode in your iOS Settings in order to use Screen Lock."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "You must enable a passcode in your iOS Settings in order to use Screen Lock."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/it.lproj/Localizable.strings b/Session/Meta/Translations/it.lproj/Localizable.strings index 5c0f62aec..007cac231 100644 --- a/Session/Meta/Translations/it.lproj/Localizable.strings +++ b/Session/Meta/Translations/it.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Fotocamera"; "accessibility_main_button_collapse" = "Comprimi opzioni allegato"; "invalid_recovery_phrase" = "Frase Di Recupero non valida"; -"invalid_recovery_phrase" = "Frase Di Ripristino Non Valida"; "DISMISS_BUTTON_TEXT" = "Chiudi"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Impostazioni"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "È possibile abilitare l'autorizzazione 'Voce e video chiamate' nelle Impostazioni Privacy."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Errore"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Autenticazione non riuscita."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Troppi tentativi di autenticazione non riusciti. Riprova più tardi."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Devi abilitare una password nelle impostazioni di iOS per poter usare il blocco schermo."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Devi abilitare una password nelle impostazioni di iOS per poter usare il blocco schermo."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Devi abilitare una password nelle impostazioni di iOS per poter usare il blocco schermo."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/ja.lproj/Localizable.strings b/Session/Meta/Translations/ja.lproj/Localizable.strings index 34f322714..f554a0bcb 100644 --- a/Session/Meta/Translations/ja.lproj/Localizable.strings +++ b/Session/Meta/Translations/ja.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "カメラ"; "accessibility_main_button_collapse" = "添付ファイルのオプションを閉じる"; "invalid_recovery_phrase" = "無効な復元フレーズ"; -"invalid_recovery_phrase" = "無効な復元フレーズ"; "DISMISS_BUTTON_TEXT" = "中止"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "設定"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "プライバシー設定から音声とビデオ通話の許可を有効にできます。"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "エラー"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "認証に失敗しました。"; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "認証失敗が多すぎます。あとで再度試してください。"; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "画面ロックを使用するには、iOSの設定でパスコードを有効にしてください。"; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "画面ロックを使用するには、iOSの設定でパスコードを有効にしてください。"; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "画面ロックを使用するには、iOSの設定でパスコードを有効にしてください。"; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/nl.lproj/Localizable.strings b/Session/Meta/Translations/nl.lproj/Localizable.strings index af4d90a7f..d2280bc06 100644 --- a/Session/Meta/Translations/nl.lproj/Localizable.strings +++ b/Session/Meta/Translations/nl.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Camera"; "accessibility_main_button_collapse" = "Bijlage-opties inklappen"; "invalid_recovery_phrase" = "Ongeldig Herstelzin"; -"invalid_recovery_phrase" = "Ongeldig Herstelzin"; "DISMISS_BUTTON_TEXT" = "Negeren"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Instellingen"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Error"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authenticatie mislukt."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Te veel pogingen tot authenticatie. Probeer het later opnieuw."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Om appvergrendeling te kunnen gebruiken, moet je een toegangscode instellen in de iOS-instellingen."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Om appvergrendeling te kunnen gebruiken, moet je een toegangscode instellen in de iOS-instellingen."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Om appvergrendeling te kunnen gebruiken, moet je een toegangscode instellen in de iOS-instellingen."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/pl.lproj/Localizable.strings b/Session/Meta/Translations/pl.lproj/Localizable.strings index 6cef8f942..7d53e7b81 100644 --- a/Session/Meta/Translations/pl.lproj/Localizable.strings +++ b/Session/Meta/Translations/pl.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Aparat"; "accessibility_main_button_collapse" = "Zwiń opcje załączników"; "invalid_recovery_phrase" = "Nieprawidłowa fraza odzyskiwania"; -"invalid_recovery_phrase" = "Nieprawidłowa fraza odzyskiwania"; "DISMISS_BUTTON_TEXT" = "Odrzuć"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Ustawienia"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "Możesz włączyć uprawnienie 'Połączenia głosowe i wideo' w Ustawieniach Prywatności."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Błąd"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Uwierzytelnianie nie powiodło się."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Zbyt wiele błędnych logowań. Spróbuj później."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Musisz włączyć kod dostępu w Ustawieniach systemu iOS, aby korzystać z blokady ekranu."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Musisz włączyć kod dostępu w Ustawieniach systemu iOS, aby korzystać z blokady ekranu."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Musisz włączyć kod dostępu w Ustawieniach systemu iOS, aby korzystać z blokady ekranu."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/pt_BR.lproj/Localizable.strings b/Session/Meta/Translations/pt_BR.lproj/Localizable.strings index 1ebe65929..8e5856689 100644 --- a/Session/Meta/Translations/pt_BR.lproj/Localizable.strings +++ b/Session/Meta/Translations/pt_BR.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Câmera"; "accessibility_main_button_collapse" = "Recolher opções de anexo"; "invalid_recovery_phrase" = "Frase de Recuperação inválida"; -"invalid_recovery_phrase" = "Frase de Recuperação inválida"; "DISMISS_BUTTON_TEXT" = "Ignorar"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Configurações"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Erro"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Falha na autenticação."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Você excedeu o número máximo permitido de tentativas de autenticação. Por favor, tente novamente mais tarde."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Você deve criar uma senha no app Ajustes do iOS para usar bloqueio de tela."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Você deve criar uma senha no app Ajustes do iOS para usar o bloqueio de tela."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Você deve criar uma senha no app Ajustes do iOS para usar o bloqueio de tela."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/ru.lproj/Localizable.strings b/Session/Meta/Translations/ru.lproj/Localizable.strings index cf4e35c0c..8e0c3f534 100644 --- a/Session/Meta/Translations/ru.lproj/Localizable.strings +++ b/Session/Meta/Translations/ru.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Камера"; "accessibility_main_button_collapse" = "Свернуть параметры вложений"; "invalid_recovery_phrase" = "Неверная секретная фраза"; -"invalid_recovery_phrase" = "Неверная секретная фраза"; "DISMISS_BUTTON_TEXT" = "Закрыть"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Настройки"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Ошибка"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Ошибка аутентификации."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Слишком много неудачных попыток аутентификации. Пожалуйста, повторите попытку позже."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Вы должны включить код доступа в приложении «Настройки», чтобы использовать блокировку экрана."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Вы должны включить код доступа в приложении «Настройки», чтобы использовать блокировку экрана."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Вы должны включить код доступа в приложении «Настройки», чтобы использовать блокировку экрана."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/si.lproj/Localizable.strings b/Session/Meta/Translations/si.lproj/Localizable.strings index 826878f56..bd1d4fd91 100644 --- a/Session/Meta/Translations/si.lproj/Localizable.strings +++ b/Session/Meta/Translations/si.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Camera"; "accessibility_main_button_collapse" = "Collapse attachment options"; "invalid_recovery_phrase" = "Invalid Recovery Phrase"; -"invalid_recovery_phrase" = "Invalid Recovery Phrase"; "DISMISS_BUTTON_TEXT" = "Dismiss"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "සැකසුම්"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Error"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication failed."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Too many failed authentication attempts. Please try again later."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "You must enable a passcode in your iOS Settings in order to use Screen Lock."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "You must enable a passcode in your iOS Settings in order to use Screen Lock."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "You must enable a passcode in your iOS Settings in order to use Screen Lock."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/sk.lproj/Localizable.strings b/Session/Meta/Translations/sk.lproj/Localizable.strings index c6330a516..6632f0943 100644 --- a/Session/Meta/Translations/sk.lproj/Localizable.strings +++ b/Session/Meta/Translations/sk.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Kamera"; "accessibility_main_button_collapse" = "Uzatvor možnosti prípon"; "invalid_recovery_phrase" = "Neplatná Obnovovacia Fráza"; -"invalid_recovery_phrase" = "Neplatná Obnovovacia Fráza"; "DISMISS_BUTTON_TEXT" = "Zrušiť"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Nastavenia"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Error"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Autentifikácia zlyhala"; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Priveľa nepodarených pokusov o autentifikáciu. Prosím, skúste to znovu neskôr."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Pre používanie zámku obrazovky, zapnite kódový zámok v nastaveniach iOS."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Pre používanie zámku obrazovky, zapnite kódový zámok v nastaveniach iOS."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Pre používanie zámku obrazovky, zapnite kódový zámok v nastaveniach iOS."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/sv.lproj/Localizable.strings b/Session/Meta/Translations/sv.lproj/Localizable.strings index 92138867f..afee13e19 100644 --- a/Session/Meta/Translations/sv.lproj/Localizable.strings +++ b/Session/Meta/Translations/sv.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Kamera"; "accessibility_main_button_collapse" = "Collapse attachment options"; "invalid_recovery_phrase" = "Invalid Recovery Phrase"; -"invalid_recovery_phrase" = "Invalid Recovery Phrase"; "DISMISS_BUTTON_TEXT" = "Dismiss"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Inställningar"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Error"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Autentisering misslyckades."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "För många misslyckade autentiseringsförsök. Försök igen senare."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Du måste aktivera en lösenkod i dina iOS-inställningar för att använda Skärmlås."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Du måste aktivera en lösenkod i dina iOS-inställningar för att använda Skärmlås."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Du måste aktivera en lösenkod i dina iOS-inställningar för att använda Skärmlås."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/th.lproj/Localizable.strings b/Session/Meta/Translations/th.lproj/Localizable.strings index 6545dea2d..6b9f85dec 100644 --- a/Session/Meta/Translations/th.lproj/Localizable.strings +++ b/Session/Meta/Translations/th.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Camera"; "accessibility_main_button_collapse" = "Collapse attachment options"; "invalid_recovery_phrase" = "Invalid Recovery Phrase"; -"invalid_recovery_phrase" = "Invalid Recovery Phrase"; "DISMISS_BUTTON_TEXT" = "Dismiss"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Settings"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Error"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "การรับรองความถูกต้องไม่สำเร็จ"; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "รับรองความถูกต้องไม่สำเร็จหลายครั้งเกินไป โปรดลองใหม่ในภายหลัง"; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "คุณต้องเปิดใช้งานรหัสผ่านในการตั้งค่า iOS ของคุณเพื่อใช้งานการล็อกหน้าจอ"; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "คุณต้องเปิดใช้งานรหัสผ่านในการตั้งค่า iOS ของคุณเพื่อใช้งานการล็อกหน้าจอ"; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "คุณต้องเปิดใช้งานรหัสผ่านในการตั้งค่า iOS ของคุณเพื่อใช้งานการล็อกหน้าจอ"; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/vi-VN.lproj/Localizable.strings b/Session/Meta/Translations/vi-VN.lproj/Localizable.strings index 58c025221..6b5e5594b 100644 --- a/Session/Meta/Translations/vi-VN.lproj/Localizable.strings +++ b/Session/Meta/Translations/vi-VN.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "Camera"; "accessibility_main_button_collapse" = "Collapse attachment options"; "invalid_recovery_phrase" = "Invalid Recovery Phrase"; -"invalid_recovery_phrase" = "Invalid Recovery Phrase"; "DISMISS_BUTTON_TEXT" = "Dismiss"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "Settings"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Error"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication failed."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Too many failed authentication attempts. Please try again later."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "You must enable a passcode in your iOS Settings in order to use Screen Lock."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "You must enable a passcode in your iOS Settings in order to use Screen Lock."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "You must enable a passcode in your iOS Settings in order to use Screen Lock."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings b/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings index f47db9db0..c389b1514 100644 --- a/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings +++ b/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "相機"; "accessibility_main_button_collapse" = "摺疊附件選項"; "invalid_recovery_phrase" = "備援暗語無效"; -"invalid_recovery_phrase" = "恢復短語無效"; "DISMISS_BUTTON_TEXT" = "關閉"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "設定"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings."; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "Error"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication failed."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Too many failed authentication attempts. Please try again later."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "You must enable a passcode in your iOS Settings in order to use Screen Lock."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "You must enable a passcode in your iOS Settings in order to use Screen Lock."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "You must enable a passcode in your iOS Settings in order to use Screen Lock."; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Meta/Translations/zh_CN.lproj/Localizable.strings b/Session/Meta/Translations/zh_CN.lproj/Localizable.strings index 820ba3c80..68bdf9b6b 100644 --- a/Session/Meta/Translations/zh_CN.lproj/Localizable.strings +++ b/Session/Meta/Translations/zh_CN.lproj/Localizable.strings @@ -606,7 +606,6 @@ "accessibility_camera_button" = "相机"; "accessibility_main_button_collapse" = "收起附件选项"; "invalid_recovery_phrase" = "恢复口令无效"; -"invalid_recovery_phrase" = "恢复口令无效"; "DISMISS_BUTTON_TEXT" = "取消"; /* Button text which opens the settings app */ "OPEN_SETTINGS_BUTTON" = "设置"; @@ -653,10 +652,36 @@ "modal_call_permission_request_explanation" = "您可以在隐私设置中启用“语音和视频通话”权限。"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred"; "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later"; -"ALERT_ERROR_TITLE" = "错误"; "LOADING_CONVERSATIONS" = "Loading Conversations..."; "DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore our device\n\nWarning: Restoring your device will result in loss of any data older than two weeks"; "CHATS_TITLE" = "Chats"; "MESSAGE_TRIMMING_TITLE" = "Message Trimming"; "MESSAGE_TRIMMING_OPEN_GROUP_TITLE" = "Delete Old Open Group Messages"; "MESSAGE_TRIMMING_OPEN_GROUP_DESCRIPTION" = "Automatically delete messages which are older than 6 months from open groups with over 2,000 messages when starting the app"; +"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again."; +"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again."; +"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "认证失败。"; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "认证失败次数太多,请稍后再试。"; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "您需要先设置您的密码来开启屏幕锁功能。"; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "您需要先设置您的密码来开启屏幕锁功能。"; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "您需要先设置您的密码来开启屏幕锁功能。"; +/* Label for the button to send a message */ +"SEND_BUTTON_TITLE" = "Send"; +/* Generic text for button that retries whatever the last action was. */ +"RETRY_BUTTON_TEXT" = "Retry"; +/* notification action */ +"SHOW_THREAD_BUTTON_TITLE" = "Show Chat"; +/* notification body */ +"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send."; +"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again."; +"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again."; diff --git a/Session/Notifications/AppNotifications.swift b/Session/Notifications/AppNotifications.swift index 49491f158..96463a3f8 100644 --- a/Session/Notifications/AppNotifications.swift +++ b/Session/Notifications/AppNotifications.swift @@ -224,11 +224,19 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { let userInfo = [ AppNotificationUserInfoKey.threadId: thread.id ] + + let userPublicKey: String = getUserHexEncodedPublicKey(db) + let userBlindedKey: String? = SessionThread.getUserHexEncodedBlindedKey( + threadId: thread.id, + threadVariant: thread.variant + ) DispatchQueue.main.async { notificationBody = MentionUtilities.highlightMentions( in: (notificationBody ?? ""), - threadVariant: thread.variant + threadVariant: thread.variant, + currentUserPublicKey: userPublicKey, + currentUserBlindedPublicKey: userBlindedKey ) let sound: Preferences.Sound? = self.requestSound(thread: thread) diff --git a/Session/Onboarding/LinkDeviceVC.swift b/Session/Onboarding/LinkDeviceVC.swift index 2d14ab3f9..5791ee005 100644 --- a/Session/Onboarding/LinkDeviceVC.swift +++ b/Session/Onboarding/LinkDeviceVC.swift @@ -128,7 +128,11 @@ final class LinkDeviceVC : BaseVC, UIPageViewControllerDataSource, UIPageViewCon func continueWithSeed(_ seed: Data) { if (seed.count != 16) { - let alert = UIAlertController(title: NSLocalizedString("invalid_recovery_phrase", comment: ""), message: NSLocalizedString("Please check the Recovery Phrase and try again.", comment: ""), preferredStyle: .alert) + let alert = UIAlertController( + title: "invalid_recovery_phrase".localized(), + message: "INVALID_RECOVERY_PHRASE_MESSAGE".localized(), + preferredStyle: .alert + ) alert.addAction(UIAlertAction(title: NSLocalizedString("BUTTON_OK", comment: ""), style: .default, handler: { _ in self.scanQRCodeWrapperVC.startCapture() })) diff --git a/Session/Settings/QRCodeVC.swift b/Session/Settings/QRCodeVC.swift index 4376809ea..be39795b0 100644 --- a/Session/Settings/QRCodeVC.swift +++ b/Session/Settings/QRCodeVC.swift @@ -121,7 +121,9 @@ final class QRCodeVC : BaseVC, UIPageViewControllerDataSource, UIPageViewControl fileprivate func startNewPrivateChatIfPossible(with hexEncodedPublicKey: String) { if !ECKeyPair.isValidHexEncodedPublicKey(candidate: hexEncodedPublicKey) { - let alert = UIAlertController(title: NSLocalizedString("invalid_session_id", comment: ""), message: NSLocalizedString("Please check the Session ID and try again.", comment: ""), preferredStyle: .alert) + let alert = UIAlertController( + title: "invalid_session_id".localized(), + message: "INVALID_SESSION_ID_MESSAGE".localized(), preferredStyle: .alert) alert.addAction(UIAlertAction(title: NSLocalizedString("BUTTON_OK", comment: ""), style: .default, handler: nil)) presentAlert(alert) } diff --git a/Session/Shared/FullConversationCell.swift b/Session/Shared/FullConversationCell.swift index 92ffebb8a..ebf55e4c2 100644 --- a/Session/Shared/FullConversationCell.swift +++ b/Session/Shared/FullConversationCell.swift @@ -267,6 +267,8 @@ public final class FullConversationCell: UITableViewCell { cellViewModel.authorName(for: .contact) : nil ), + currentUserPublicKey: cellViewModel.currentUserPublicKey, + currentUserBlindedPublicKey: cellViewModel.currentUserBlindedPublicKey, searchText: searchText.lowercased(), fontSize: Values.smallFontSize ) @@ -288,6 +290,8 @@ public final class FullConversationCell: UITableViewCell { timestampLabel.isHidden = true displayNameLabel.attributedText = getHighlightedSnippet( content: cellViewModel.displayName, + currentUserPublicKey: cellViewModel.currentUserPublicKey, + currentUserBlindedPublicKey: cellViewModel.currentUserBlindedPublicKey, searchText: searchText.lowercased(), fontSize: Values.mediumFontSize ) @@ -299,6 +303,8 @@ public final class FullConversationCell: UITableViewCell { bottomLabelStackView.isHidden = (cellViewModel.threadMemberNames ?? "").isEmpty snippetLabel.attributedText = getHighlightedSnippet( content: (cellViewModel.threadMemberNames ?? ""), + currentUserPublicKey: cellViewModel.currentUserPublicKey, + currentUserBlindedPublicKey: cellViewModel.currentUserBlindedPublicKey, searchText: searchText.lowercased(), fontSize: Values.smallFontSize ) @@ -440,7 +446,9 @@ public final class FullConversationCell: UITableViewCell { attachmentCount: cellViewModel.interactionAttachmentCount, isOpenGroupInvitation: (cellViewModel.interactionIsOpenGroupInvitation == true) ), - threadVariant: cellViewModel.threadVariant + threadVariant: cellViewModel.threadVariant, + currentUserPublicKey: cellViewModel.currentUserPublicKey, + currentUserBlindedPublicKey: cellViewModel.currentUserBlindedPublicKey ), attributes: [ .font: font, @@ -454,6 +462,8 @@ public final class FullConversationCell: UITableViewCell { private func getHighlightedSnippet( content: String, authorName: String? = nil, + currentUserPublicKey: String, + currentUserBlindedPublicKey: String?, searchText: String, fontSize: CGFloat ) -> NSAttributedString { @@ -473,7 +483,9 @@ public final class FullConversationCell: UITableViewCell { // we don't want to include the truncated id as part of the name so we exclude it let mentionReplacedContent: String = MentionUtilities.highlightMentions( in: content, - threadVariant: .contact + threadVariant: .contact, + currentUserPublicKey: currentUserPublicKey, + currentUserBlindedPublicKey: currentUserBlindedPublicKey ) let result: NSMutableAttributedString = NSMutableAttributedString( string: mentionReplacedContent, diff --git a/Session/Shared/HighlightMentionBackgroundView.swift b/Session/Shared/HighlightMentionBackgroundView.swift new file mode 100644 index 000000000..1b9a593ba --- /dev/null +++ b/Session/Shared/HighlightMentionBackgroundView.swift @@ -0,0 +1,161 @@ +// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. + +import UIKit + +public extension NSAttributedString.Key { + static let currentUserMentionBackgroundColor: NSAttributedString.Key = NSAttributedString.Key(rawValue: "currentUserMentionBackgroundColor") + static let currentUserMentionBackgroundCornerRadius: NSAttributedString.Key = NSAttributedString.Key(rawValue: "currentUserMentionBackgroundCornerRadius") + static let currentUserMentionBackgroundPadding: NSAttributedString.Key = NSAttributedString.Key(rawValue: "currentUserMentionBackgroundPadding") +} + +class HighlightMentionBackgroundView: UIView { + var maxPadding: CGFloat = 0 + + init() { + super.init(frame: .zero) + + self.isOpaque = false + self.layer.zPosition = -1 + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Functions + + public func calculateMaxPadding(for attributedText: NSAttributedString) -> CGFloat { + var allMentionRadii: [CGFloat?] = [] + let path: CGMutablePath = CGMutablePath() + path.addRect(CGRect( + x: 0, + y: 0, + width: CGFloat.greatestFiniteMagnitude, + height: CGFloat.greatestFiniteMagnitude + )) + + let framesetter = CTFramesetterCreateWithAttributedString(attributedText as CFAttributedString) + let frame: CTFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, attributedText.length), path, nil) + let lines: [CTLine] = frame.lines + + lines.forEach { line in + let runs: [CTRun] = line.ctruns + + runs.forEach { run in + let attributes: NSDictionary = CTRunGetAttributes(run) + allMentionRadii.append( + attributes + .value(forKey: NSAttributedString.Key.currentUserMentionBackgroundPadding.rawValue) as? CGFloat + ) + } + } + + return allMentionRadii + .compactMap { $0 } + .max() + .defaulting(to: 0) + } + + // MARK: - Drawing + + override func draw(_ rect: CGRect) { + guard + let superview: UITextView = (self.superview as? UITextView), + let context = UIGraphicsGetCurrentContext() + else { return } + + // Need to invery the Y axis because iOS likes to render from the bottom left instead of the top left + context.textMatrix = .identity + context.translateBy(x: 0, y: bounds.size.height) + context.scaleBy(x: 1.0, y: -1.0) + + // Note: Calculations MUST happen based on the 'superview' size as this class has extra padding which + // can result in calculations being off + let path = CGMutablePath() + let size = superview.sizeThatFits(CGSize(width: superview.bounds.width, height: .greatestFiniteMagnitude)) + path.addRect(CGRect(x: 0, y: 0, width: size.width, height: size.height), transform: .identity) + + let framesetter = CTFramesetterCreateWithAttributedString(superview.attributedText as CFAttributedString) + let frame: CTFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, superview.attributedText.length), path, nil) + let lines: [CTLine] = frame.lines + + var origins = [CGPoint](repeating: .zero, count: lines.count) + CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), &origins) + + for lineIndex in 0.. lineWidth ? lineWidth : runBounds.width) + + let path = UIBezierPath(roundedRect: runBounds, cornerRadius: cornerRadius) + mentionBackgroundColor.setFill() + path.fill() + } + } + } +} + +extension CTFrame { + var lines: [CTLine] { + return ((CTFrameGetLines(self) as [AnyObject] as? [CTLine]) ?? []) + } +} + +extension CTLine { + var ctruns: [CTRun] { + return ((CTLineGetGlyphRuns(self) as [AnyObject] as? [CTRun]) ?? []) + } +} diff --git a/Session/Shared/ScanQRCodeWrapperVC.swift b/Session/Shared/ScanQRCodeWrapperVC.swift index e3a8c07e2..2d8241569 100644 --- a/Session/Shared/ScanQRCodeWrapperVC.swift +++ b/Session/Shared/ScanQRCodeWrapperVC.swift @@ -56,7 +56,7 @@ final class ScanQRCodeWrapperVC : BaseVC { explanationLabel.autoPinWidthToSuperview(withMargin: 32) explanationLabel.autoPinHeightToSuperview(withMargin: 32) // Title - title = NSLocalizedString("Scan QR Code", comment: "") + title = "Scan QR Code" } override func viewDidAppear(_ animated: Bool) { diff --git a/Session/Utilities/MentionUtilities.swift b/Session/Utilities/MentionUtilities.swift index 104deaaea..f5876d5d6 100644 --- a/Session/Utilities/MentionUtilities.swift +++ b/Session/Utilities/MentionUtilities.swift @@ -6,10 +6,17 @@ import SessionUIKit import SessionMessagingKit public enum MentionUtilities { - public static func highlightMentions(in string: String, threadVariant: SessionThread.Variant) -> String { + public static func highlightMentions( + in string: String, + threadVariant: SessionThread.Variant, + currentUserPublicKey: String, + currentUserBlindedPublicKey: String? + ) -> String { return highlightMentions( in: string, threadVariant: threadVariant, + currentUserPublicKey: currentUserPublicKey, + currentUserBlindedPublicKey: currentUserBlindedPublicKey, isOutgoingMessage: false, attributes: [:] ).string // isOutgoingMessage and attributes are irrelevant @@ -18,6 +25,8 @@ public enum MentionUtilities { public static func highlightMentions( in string: String, threadVariant: SessionThread.Variant, + currentUserPublicKey: String?, + currentUserBlindedPublicKey: String?, isOutgoingMessage: Bool, attributes: [NSAttributedString.Key: Any] ) -> NSAttributedString { @@ -29,7 +38,13 @@ public enum MentionUtilities { var string = string var lastMatchEnd: Int = 0 - var mentions: [(range: NSRange, publicKey: String)] = [] + var mentions: [(range: NSRange, isCurrentUser: Bool)] = [] + let currentUserPublicKeys: Set = [ + currentUserPublicKey, + currentUserBlindedPublicKey + ] + .compactMap { $0 } + .asSet() while let match: NSTextCheckingResult = regex.firstMatch( in: string, @@ -39,28 +54,52 @@ public enum MentionUtilities { guard let range: Range = Range(match.range, in: string) else { break } let publicKey: String = String(string[range].dropFirst()) // Drop the @ + let isCurrentUser: Bool = currentUserPublicKeys.contains(publicKey) - guard let displayName: String = Profile.displayNameNoFallback(id: publicKey, threadVariant: threadVariant) else { - lastMatchEnd = (match.range.location + match.range.length) - continue - } + guard let targetString: String = { + guard !isCurrentUser else { return "MEDIA_GALLERY_SENDER_NAME_YOU".localized() } + guard let displayName: String = Profile.displayNameNoFallback(id: publicKey, threadVariant: threadVariant) else { + lastMatchEnd = (match.range.location + match.range.length) + return nil + } + + return displayName + }() + else { continue } - string = string.replacingCharacters(in: range, with: "@\(displayName)") - lastMatchEnd = (match.range.location + displayName.utf16.count) + string = string.replacingCharacters(in: range, with: "@\(targetString)") + lastMatchEnd = (match.range.location + targetString.utf16.count) mentions.append(( // + 1 to include the @ - range: NSRange(location: match.range.location, length: displayName.utf16.count + 1), - publicKey: publicKey + range: NSRange(location: match.range.location, length: targetString.utf16.count + 1), + isCurrentUser: isCurrentUser )) } + let sizeDiff: CGFloat = (Values.smallFontSize / Values.mediumFontSize) let result: NSMutableAttributedString = NSMutableAttributedString(string: string, attributes: attributes) mentions.forEach { mention in - // FIXME: This might break when swapping between themes - let color = isOutgoingMessage ? (isLightMode ? .white : .black) : Colors.accent - result.addAttribute(.foregroundColor, value: color, range: mention.range) result.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: Values.smallFontSize), range: mention.range) + + if mention.isCurrentUser { + // Note: The designs don't match with the dynamic sizing so these values need to be calculated + // to maintain a "rounded rect" effect rather than a "pill" effect + result.addAttribute(.currentUserMentionBackgroundCornerRadius, value: (8 * sizeDiff), range: mention.range) + result.addAttribute(.currentUserMentionBackgroundPadding, value: (3 * sizeDiff), range: mention.range) + result.addAttribute(.currentUserMentionBackgroundColor, value: Colors.accent, range: mention.range) + result.addAttribute(.foregroundColor, value: UIColor.black, range: mention.range) + } + else { + let color: UIColor = { + switch (isLightMode, isOutgoingMessage) { + case (_, true): return .black + case (true, false): return .black + case (false, false): return Colors.accent + } + }() + result.addAttribute(.foregroundColor, value: color, range: mention.range) + } } return result diff --git a/SessionMessagingKit/Database/Models/Profile.swift b/SessionMessagingKit/Database/Models/Profile.swift index 32385683b..e57a95422 100644 --- a/SessionMessagingKit/Database/Models/Profile.swift +++ b/SessionMessagingKit/Database/Models/Profile.swift @@ -314,14 +314,11 @@ public extension Profile { /// A standardised mechanism for truncating a user id for a given thread static func truncated(id: String, threadVariant: SessionThread.Variant = .contact) -> String { - switch threadVariant { - case .openGroup: return truncated(id: id, truncating: .start) - default: return truncated(id: id, truncating: .middle) - } + return truncated(id: id, truncating: .middle) } /// A standardised mechanism for truncating a user id - static func truncated(id: String, truncating: Truncation = .start) -> String { + static func truncated(id: String, truncating: Truncation = .middle) -> String { guard id.count > 8 else { return id } switch truncating { @@ -355,7 +352,7 @@ public extension Profile { case .openGroup: // In open groups, where it's more likely that multiple users have the same name, // we display a bit of the Session ID after a user's display name for added context - return "\(name) (\(Profile.truncated(id: id, truncating: .start)))" + return "\(name) (\(Profile.truncated(id: id, truncating: .middle)))" } } } diff --git a/SessionMessagingKit/Database/Models/SessionThread.swift b/SessionMessagingKit/Database/Models/SessionThread.swift index 9f0967104..1b4e55169 100644 --- a/SessionMessagingKit/Database/Models/SessionThread.swift +++ b/SessionMessagingKit/Database/Models/SessionThread.swift @@ -2,6 +2,7 @@ import Foundation import GRDB +import Sodium import SessionUtilitiesKit public struct SessionThread: Codable, Identifiable, Equatable, FetchableRecord, PersistableRecord, TableRecord, ColumnExpressible { @@ -314,6 +315,39 @@ public extension SessionThread { return profile.displayName() } } + + static func getUserHexEncodedBlindedKey( + threadId: String, + threadVariant: Variant + ) -> String? { + guard + threadVariant == .openGroup, + let blindingInfo: (edkeyPair: Box.KeyPair?, publicKey: String?) = Storage.shared.read({ db in + return ( + Identity.fetchUserEd25519KeyPair(db), + try OpenGroup + .filter(id: threadId) + .select(.publicKey) + .asRequest(of: String.self) + .fetchOne(db) + ) + }), + let userEdKeyPair: Box.KeyPair = blindingInfo.edkeyPair, + let publicKey: String = blindingInfo.publicKey + else { return nil } + + let sodium: Sodium = Sodium() + + let blindedKeyPair: Box.KeyPair? = sodium.blindedKeyPair( + serverPublicKey: publicKey, + edKeyPair: userEdKeyPair, + genericHash: sodium.getGenericHash() + ) + + return blindedKeyPair.map { keyPair -> String in + SessionId(.blinded, publicKey: keyPair.publicKey).hexString + } + } } // MARK: - Objective-C Support diff --git a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageSender+ClosedGroups.swift b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageSender+ClosedGroups.swift index a52576076..ff813332e 100644 --- a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageSender+ClosedGroups.swift +++ b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageSender+ClosedGroups.swift @@ -44,11 +44,11 @@ extension MessageSender { // Send a closed group update message to all members individually var promises: [Promise] = [] - try members.forEach { adminId in + try members.forEach { memberId in try GroupMember( groupId: groupPublicKey, - profileId: adminId, - role: .admin + profileId: memberId, + role: .standard ).insert(db) } diff --git a/SessionMessagingKit/Shared Models/MessageViewModel.swift b/SessionMessagingKit/Shared Models/MessageViewModel.swift index 9e7467c99..bad4cb96e 100644 --- a/SessionMessagingKit/Shared Models/MessageViewModel.swift +++ b/SessionMessagingKit/Shared Models/MessageViewModel.swift @@ -29,6 +29,7 @@ public struct MessageViewModel: FetchableRecordWithRowId, Decodable, Equatable, public static let quoteAttachmentKey: SQL = SQL(stringLiteral: CodingKeys.quoteAttachment.stringValue) public static let linkPreviewKey: SQL = SQL(stringLiteral: CodingKeys.linkPreview.stringValue) public static let linkPreviewAttachmentKey: SQL = SQL(stringLiteral: CodingKeys.linkPreviewAttachment.stringValue) + public static let currentUserPublicKeyKey: SQL = SQL(stringLiteral: CodingKeys.currentUserPublicKey.stringValue) public static let cellTypeKey: SQL = SQL(stringLiteral: CodingKeys.cellType.stringValue) public static let authorNameKey: SQL = SQL(stringLiteral: CodingKeys.authorName.stringValue) public static let shouldShowProfileKey: SQL = SQL(stringLiteral: CodingKeys.shouldShowProfile.stringValue) @@ -92,6 +93,8 @@ public struct MessageViewModel: FetchableRecordWithRowId, Decodable, Equatable, public let linkPreview: LinkPreview? public let linkPreviewAttachment: Attachment? + public let currentUserPublicKey: String + // Post-Query Processing Data /// This value includes the associated attachments @@ -132,6 +135,9 @@ public struct MessageViewModel: FetchableRecordWithRowId, Decodable, Equatable, /// This value indicates whether this is the last message in the thread public let isLast: Bool + + /// This is the users blinded key (will only be set for messages within open groups) + public let currentUserBlindedPublicKey: String? // MARK: - Mutation @@ -164,6 +170,7 @@ public struct MessageViewModel: FetchableRecordWithRowId, Decodable, Equatable, quoteAttachment: self.quoteAttachment, linkPreview: self.linkPreview, linkPreviewAttachment: self.linkPreviewAttachment, + currentUserPublicKey: self.currentUserPublicKey, attachments: attachments, cellType: self.cellType, authorName: self.authorName, @@ -175,14 +182,16 @@ public struct MessageViewModel: FetchableRecordWithRowId, Decodable, Equatable, previousVariant: self.previousVariant, positionInCluster: self.positionInCluster, isOnlyMessageInCluster: self.isOnlyMessageInCluster, - isLast: self.isLast + isLast: self.isLast, + currentUserBlindedPublicKey: self.currentUserBlindedPublicKey ) } public func withClusteringChanges( prevModel: MessageViewModel?, nextModel: MessageViewModel?, - isLast: Bool + isLast: Bool, + currentUserBlindedPublicKey: String? ) -> MessageViewModel { let cellType: CellType = { guard self.isTypingIndicator != true else { return .typingIndicator } @@ -338,6 +347,7 @@ public struct MessageViewModel: FetchableRecordWithRowId, Decodable, Equatable, quoteAttachment: self.quoteAttachment, linkPreview: self.linkPreview, linkPreviewAttachment: self.linkPreviewAttachment, + currentUserPublicKey: self.currentUserPublicKey, attachments: self.attachments, cellType: cellType, authorName: authorDisplayName, @@ -385,7 +395,8 @@ public struct MessageViewModel: FetchableRecordWithRowId, Decodable, Equatable, previousVariant: prevModel?.variant, positionInCluster: positionInCluster, isOnlyMessageInCluster: isOnlyMessageInCluster, - isLast: isLast + isLast: isLast, + currentUserBlindedPublicKey: currentUserBlindedPublicKey ) } } @@ -478,6 +489,7 @@ public extension MessageViewModel { self.quoteAttachment = nil self.linkPreview = nil self.linkPreviewAttachment = nil + self.currentUserPublicKey = "" // Post-Query Processing Data @@ -493,6 +505,7 @@ public extension MessageViewModel { self.positionInCluster = .middle self.isOnlyMessageInCluster = true self.isLast = true + self.currentUserBlindedPublicKey = nil } } @@ -557,7 +570,11 @@ public extension MessageViewModel { return SQL("\(interaction[.timestampMs].desc)") }() - static func baseQuery(orderSQL: SQL, groupSQL: SQL?) -> (([Int64]) -> AdaptedFetchRequest>) { + static func baseQuery( + userPublicKey: String, + orderSQL: SQL, + groupSQL: SQL? + ) -> (([Int64]) -> AdaptedFetchRequest>) { return { rowIds -> AdaptedFetchRequest> in let interaction: TypedTableAlias = TypedTableAlias() let thread: TypedTableAlias = TypedTableAlias() @@ -621,6 +638,8 @@ public extension MessageViewModel { \(ViewModel.linkPreviewKey).*, \(ViewModel.linkPreviewAttachmentKey).*, + \(SQL("\(userPublicKey)")) AS \(ViewModel.currentUserPublicKeyKey), + -- All of the below properties are set in post-query processing but to prevent the -- query from crashing when decoding we need to provide default values \(CellType.textOnlyMessage) AS \(ViewModel.cellTypeKey), diff --git a/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift b/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift index fc099a5cb..bb78b6940 100644 --- a/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift +++ b/SessionMessagingKit/Shared Models/SessionThreadViewModel.swift @@ -2,6 +2,7 @@ import Foundation import GRDB +import Sodium import DifferenceKit import SessionUtilitiesKit @@ -124,6 +125,7 @@ public struct SessionThreadViewModel: FetchableRecordWithRowId, Decodable, Equat private let threadContactNameInternal: String? private let authorNameInternal: String? public let currentUserPublicKey: String + public let currentUserBlindedPublicKey: String? // UI specific logic @@ -275,6 +277,67 @@ public extension SessionThreadViewModel { self.threadContactNameInternal = nil self.authorNameInternal = nil self.currentUserPublicKey = getUserHexEncodedPublicKey() + self.currentUserBlindedPublicKey = nil + } +} + +// MARK: - Mutation + +public extension SessionThreadViewModel { + func populatingCurrentUserBlindedKey( + currentUserBlindedPublicKeyForThisThread: String? = nil + ) -> SessionThreadViewModel { + return SessionThreadViewModel( + rowId: self.rowId, + threadId: self.threadId, + threadVariant: self.threadVariant, + threadCreationDateTimestamp: self.threadCreationDateTimestamp, + threadMemberNames: self.threadMemberNames, + threadIsNoteToSelf: self.threadIsNoteToSelf, + threadIsMessageRequest: self.threadIsMessageRequest, + threadRequiresApproval: self.threadRequiresApproval, + threadShouldBeVisible: self.threadShouldBeVisible, + threadIsPinned: self.threadIsPinned, + threadIsBlocked: self.threadIsBlocked, + threadMutedUntilTimestamp: self.threadMutedUntilTimestamp, + threadOnlyNotifyForMentions: self.threadOnlyNotifyForMentions, + threadMessageDraft: self.threadMessageDraft, + threadContactIsTyping: self.threadContactIsTyping, + threadUnreadCount: self.threadUnreadCount, + threadUnreadMentionCount: self.threadUnreadMentionCount, + contactProfile: self.contactProfile, + closedGroupProfileFront: self.closedGroupProfileFront, + closedGroupProfileBack: self.closedGroupProfileBack, + closedGroupProfileBackFallback: self.closedGroupProfileBackFallback, + closedGroupName: self.closedGroupName, + closedGroupUserCount: self.closedGroupUserCount, + currentUserIsClosedGroupMember: self.currentUserIsClosedGroupMember, + currentUserIsClosedGroupAdmin: self.currentUserIsClosedGroupAdmin, + openGroupName: self.openGroupName, + openGroupServer: self.openGroupServer, + openGroupRoomToken: self.openGroupRoomToken, + openGroupProfilePictureData: self.openGroupProfilePictureData, + openGroupUserCount: self.openGroupUserCount, + interactionId: self.interactionId, + interactionVariant: self.interactionVariant, + interactionTimestampMs: self.interactionTimestampMs, + interactionBody: self.interactionBody, + interactionState: self.interactionState, + interactionIsOpenGroupInvitation: self.interactionIsOpenGroupInvitation, + interactionAttachmentDescriptionInfo: self.interactionAttachmentDescriptionInfo, + interactionAttachmentCount: self.interactionAttachmentCount, + authorId: self.authorId, + threadContactNameInternal: self.threadContactNameInternal, + authorNameInternal: self.authorNameInternal, + currentUserPublicKey: self.currentUserPublicKey, + currentUserBlindedPublicKey: ( + currentUserBlindedPublicKeyForThisThread ?? + SessionThread.getUserHexEncodedBlindedKey( + threadId: self.threadId, + threadVariant: self.threadVariant + ) + ) + ) } } diff --git a/SessionSnodeKit/Models/SnodeAPIEndpoint.swift b/SessionSnodeKit/Models/SnodeAPIEndpoint.swift index 1028740fe..63ffd5334 100644 --- a/SessionSnodeKit/Models/SnodeAPIEndpoint.swift +++ b/SessionSnodeKit/Models/SnodeAPIEndpoint.swift @@ -11,4 +11,6 @@ public enum SnodeAPIEndpoint: String { case getInfo = "info" case clearAllData = "delete_all" case expire = "expire" + case batch = "batch" + case sequence = "sequence" } diff --git a/SessionUIKit/Components/SearchBar.swift b/SessionUIKit/Components/SearchBar.swift index ecefdca22..830f0973f 100644 --- a/SessionUIKit/Components/SearchBar.swift +++ b/SessionUIKit/Components/SearchBar.swift @@ -26,7 +26,7 @@ public extension UISearchBar { let searchTextField: UITextField = self.searchTextField searchTextField.backgroundColor = Colors.searchBarBackground // The search bar background color searchTextField.textColor = Colors.text - searchTextField.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("Search", comment: ""), attributes: [ .foregroundColor : Colors.searchBarPlaceholder ]) + searchTextField.attributedPlaceholder = NSAttributedString(string: "Search", attributes: [ .foregroundColor : Colors.searchBarPlaceholder ]) setPositionAdjustment(UIOffset(horizontal: 4, vertical: 0), for: UISearchBar.Icon.search) searchTextPositionAdjustment = UIOffset(horizontal: 2, vertical: 0) setPositionAdjustment(UIOffset(horizontal: -4, vertical: 0), for: UISearchBar.Icon.clear) diff --git a/SessionUtilitiesKit/Crypto/Mnemonic.swift b/SessionUtilitiesKit/Crypto/Mnemonic.swift index 1786f5e72..b420a89f7 100644 --- a/SessionUtilitiesKit/Crypto/Mnemonic.swift +++ b/SessionUtilitiesKit/Crypto/Mnemonic.swift @@ -48,11 +48,11 @@ public enum Mnemonic { public var errorDescription: String? { switch self { - case .generic: return NSLocalizedString("Something went wrong. Please check your recovery phrase and try again.", comment: "") - case .inputTooShort: return NSLocalizedString("Looks like you didn't enter enough words. Please check your recovery phrase and try again.", comment: "") - case .missingLastWord: return NSLocalizedString("You seem to be missing the last word of your recovery phrase. Please check what you entered and try again.", comment: "") - case .invalidWord: return NSLocalizedString("There appears to be an invalid word in your recovery phrase. Please check what you entered and try again.", comment: "") - case .verificationFailed: return NSLocalizedString("Your recovery phrase couldn't be verified. Please check what you entered and try again.", comment: "") + case .generic: return "RECOVERY_PHASE_ERROR_GENERIC".localized() + case .inputTooShort: return "RECOVERY_PHASE_ERROR_LENGTH".localized() + case .missingLastWord: return "RECOVERY_PHASE_ERROR_LAST_WORD".localized() + case .invalidWord: return "RECOVERY_PHASE_ERROR_INVALID_WORD".localized() + case .verificationFailed: return "RECOVERY_PHASE_ERROR_FAILED".localized() } } } diff --git a/SignalUtilitiesKit/Media Viewing & Editing/Attachment Approval/AttachmentTextToolbar.swift b/SignalUtilitiesKit/Media Viewing & Editing/Attachment Approval/AttachmentTextToolbar.swift index f5dcf5963..01bb11578 100644 --- a/SignalUtilitiesKit/Media Viewing & Editing/Attachment Approval/AttachmentTextToolbar.swift +++ b/SignalUtilitiesKit/Media Viewing & Editing/Attachment Approval/AttachmentTextToolbar.swift @@ -164,7 +164,7 @@ class AttachmentTextToolbar: UIView, UITextViewDelegate { private lazy var placeholderTextView: UITextView = { let placeholderTextView = buildTextView() - placeholderTextView.text = NSLocalizedString("Message", comment: "") + placeholderTextView.text = "Message" placeholderTextView.isEditable = false return placeholderTextView diff --git a/SignalUtilitiesKit/Screen Lock/OWSScreenLock.swift b/SignalUtilitiesKit/Screen Lock/OWSScreenLock.swift index dfa7a7279..306bac424 100644 --- a/SignalUtilitiesKit/Screen Lock/OWSScreenLock.swift +++ b/SignalUtilitiesKit/Screen Lock/OWSScreenLock.swift @@ -118,8 +118,7 @@ import SessionMessagingKit completion completionParam: @escaping ((OWSScreenLockOutcome) -> Void)) { AssertIsOnMainThread() - let defaultErrorDescription = NSLocalizedString("SCREEN_LOCK_ENABLE_UNKNOWN_ERROR", - comment: "Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode.") + let defaultErrorDescription = "SCREEN_LOCK_ENABLE_UNKNOWN_ERROR".localized() // Ensure completion is always called on the main thread. let completion = { (outcome: OWSScreenLockOutcome) in @@ -140,7 +139,7 @@ import SessionMessagingKit switch outcome { case .success: owsFailDebug("local authentication unexpected success") - completion(.failure(error:defaultErrorDescription)) + completion(.failure(error: defaultErrorDescription)) case .cancel, .failure, .unexpectedFailure: completion(outcome) } @@ -177,16 +176,13 @@ import SessionMessagingKit switch laError.code { case .biometryNotAvailable: Logger.error("local authentication error: biometryNotAvailable.") - return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE", - comment: "Indicates that Touch ID/Face ID/Phone Passcode are not available on this device.")) + return .failure(error: "SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE".localized()) case .biometryNotEnrolled: Logger.error("local authentication error: biometryNotEnrolled.") - return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED", - comment: "Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device.")) + return .failure(error: "SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED".localized()) case .biometryLockout: Logger.error("local authentication error: biometryLockout.") - return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT", - comment: "Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures.")) + return .failure(error: "SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT".localized()) default: // Fall through to second switch break @@ -195,27 +191,22 @@ import SessionMessagingKit switch laError.code { case .authenticationFailed: Logger.error("local authentication error: authenticationFailed.") - return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED", - comment: "Indicates that Touch ID/Face ID/Phone Passcode authentication failed.")) + return .failure(error: "SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED".localized()) case .userCancel, .userFallback, .systemCancel, .appCancel: Logger.info("local authentication cancelled.") return .cancel case .passcodeNotSet: Logger.error("local authentication error: passcodeNotSet.") - return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET", - comment: "Indicates that Touch ID/Face ID/Phone Passcode passcode is not set.")) + return .failure(error: "SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET".localized()) case .touchIDNotAvailable: Logger.error("local authentication error: touchIDNotAvailable.") - return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE", - comment: "Indicates that Touch ID/Face ID/Phone Passcode are not available on this device.")) + return .failure(error: "SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE".localized()) case .touchIDNotEnrolled: Logger.error("local authentication error: touchIDNotEnrolled.") - return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED", - comment: "Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device.")) + return .failure(error: "SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED".localized()) case .touchIDLockout: Logger.error("local authentication error: touchIDLockout.") - return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT", - comment: "Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures.")) + return .failure(error: "SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT".localized()) case .invalidContext: owsFailDebug("context not valid.") return .unexpectedFailure(error:defaultErrorDescription) diff --git a/SignalUtilitiesKit/Utilities/CommonStrings.swift b/SignalUtilitiesKit/Utilities/CommonStrings.swift index 0bcac0c4f..b3c7f6c88 100644 --- a/SignalUtilitiesKit/Utilities/CommonStrings.swift +++ b/SignalUtilitiesKit/Utilities/CommonStrings.swift @@ -16,7 +16,7 @@ import Foundation @objc static public let doneButton = NSLocalizedString("BUTTON_DONE", comment: "Label for generic done button.") @objc - static public let retryButton = NSLocalizedString("RETRY_BUTTON_TEXT", comment: "Generic text for button that retries whatever the last action was.") + static public let retryButton = "RETRY_BUTTON_TEXT".localized() @objc static public let openSettingsButton = NSLocalizedString("OPEN_SETTINGS_BUTTON", comment: "Button text which opens the settings app") @objc @@ -31,20 +31,11 @@ import Foundation static public let markAsReadNotificationAction = NSLocalizedString("PUSH_MANAGER_MARKREAD", comment: "Notification action button title") @objc - static public let sendButton = NSLocalizedString("SEND_BUTTON_TITLE", comment: "Label for the button to send a message") + static public let sendButton = "SEND_BUTTON_TITLE".localized() } @objc public class NotificationStrings: NSObject { - @objc - static public let incomingCallBody = NSLocalizedString("CALL_INCOMING_NOTIFICATION_BODY", comment: "notification body") - - @objc - static public let missedCallBody = NSLocalizedString("CALL_MISSED_NOTIFICATION_BODY", comment: "notification body") - - @objc - static public let missedCallBecauseOfIdentityChangeBody = NSLocalizedString("CALL_MISSED_BECAUSE_OF_IDENTITY_CHANGE_NOTIFICATION_BODY", comment: "notification body") - @objc static public let incomingMessageBody = NSLocalizedString("APN_Message", comment: "notification body") @@ -55,41 +46,16 @@ public class NotificationStrings: NSObject { static public let incomingGroupMessageTitleFormat = NSLocalizedString("NEW_GROUP_MESSAGE_NOTIFICATION_TITLE", comment: "notification title. Embeds {{author name}} and {{group name}}") @objc - static public let failedToSendBody = NSLocalizedString("SEND_FAILED_NOTIFICATION_BODY", comment: "notification body") + static public let failedToSendBody = "SEND_FAILED_NOTIFICATION_BODY".localized() } @objc public class CallStrings: NSObject { - @objc - static public let callStatusFormat = NSLocalizedString("CALL_STATUS_FORMAT", comment: "embeds {{Call Status}} in call screen label. For ongoing calls, {{Call Status}} is a seconds timer like 01:23, otherwise {{Call Status}} is a short text like 'Ringing', 'Busy', or 'Failed Call'") - - @objc - static public let confirmAndCallButtonTitle = NSLocalizedString("SAFETY_NUMBER_CHANGED_CONFIRM_CALL_ACTION", comment: "alert button text to confirm placing an outgoing call after the recipients Safety Number has changed.") - - @objc - static public let callBackAlertTitle = NSLocalizedString("CALL_USER_ALERT_TITLE", comment: "Title for alert offering to call a user.") - @objc - static public let callBackAlertMessageFormat = NSLocalizedString("CALL_USER_ALERT_MESSAGE_FORMAT", comment: "Message format for alert offering to call a user. Embeds {{the user's display name or phone number}}.") - @objc - static public let callBackAlertCallButton = NSLocalizedString("CALL_USER_ALERT_CALL_BUTTON", comment: "Label for call button for alert offering to call a user.") - // MARK: Notification actions @objc - static public let callBackButtonTitle = NSLocalizedString("CALLBACK_BUTTON_TITLE", comment: "notification action") - @objc - static public let showThreadButtonTitle = NSLocalizedString("SHOW_THREAD_BUTTON_TITLE", comment: "notification action") - @objc - static public let answerCallButtonTitle = NSLocalizedString("ANSWER_CALL_BUTTON_TITLE", comment: "notification action") - @objc - static public let declineCallButtonTitle = NSLocalizedString("REJECT_CALL_BUTTON_TITLE", comment: "notification action") + static public let showThreadButtonTitle = "SHOW_THREAD_BUTTON_TITLE".localized() } @objc public class MediaStrings: NSObject { @objc static public let allMedia = NSLocalizedString("MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON", comment: "nav bar button item") } - -@objc public class SafetyNumberStrings: NSObject { - @objc - static public let confirmSendButton = NSLocalizedString("SAFETY_NUMBER_CHANGED_CONFIRM_SEND_ACTION", - comment: "button title to confirm sending to a recipient whose safety number recently changed") -} diff --git a/SignalUtilitiesKit/Utilities/OWSAlerts.swift b/SignalUtilitiesKit/Utilities/OWSAlerts.swift index caa9d7e6d..f8cc99beb 100644 --- a/SignalUtilitiesKit/Utilities/OWSAlerts.swift +++ b/SignalUtilitiesKit/Utilities/OWSAlerts.swift @@ -6,25 +6,6 @@ import Foundation import SessionUtilitiesKit @objc public class OWSAlerts: NSObject { - - /// Cleanup and present alert for no permissions - @objc - public class func showNoMicrophonePermissionAlert() { - let alertTitle = NSLocalizedString("CALL_AUDIO_PERMISSION_TITLE", comment: "Alert title when calling and permissions for microphone are missing") - let alertMessage = NSLocalizedString("CALL_AUDIO_PERMISSION_MESSAGE", comment: "Alert message when calling and permissions for microphone are missing") - let alert = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .alert) - - let dismissAction = UIAlertAction(title: CommonStrings.dismissButton, style: .cancel) - dismissAction.accessibilityIdentifier = "OWSAlerts.\("dismiss")" - alert.addAction(dismissAction) - - if let settingsAction = CurrentAppContext().openSystemSettingsAction { - settingsAction.accessibilityIdentifier = "OWSAlerts.\("settings")" - alert.addAction(settingsAction) - } - CurrentAppContext().frontmostViewController()?.presentAlert(alert) - } - @objc public class func showAlert(_ alert: UIAlertController) { guard let frontmostViewController = CurrentAppContext().frontmostViewController() else {