Merge branch 'master' into master-android

This commit is contained in:
Evgeny Poberezkin
2025-05-12 17:00:14 +01:00
147 changed files with 3489 additions and 1652 deletions
+1
View File
@@ -169,6 +169,7 @@ It is possible to donate via:
- ETH: 0xD9ee7Db0AD0dc1Dfa7eD53290199ED06beA04692
- USDT (Ethereum): 0xD9ee7Db0AD0dc1Dfa7eD53290199ED06beA04692
- ZEC: t1fwjQW5gpFhDqXNhxqDWyF9j9WeKvVS5Jg
- ZEC shielded: u16rnvkflumf5uw9frngc2lymvmzgdr2mmc9unyu0l44unwfmdcpfm0axujd2w34ct3ye709azxsqge45705lpvvqu264ltzvfay55ygyq
- DOGE: D99pV4n9TrPxBPCkQGx4w4SMSa6QjRBxPf
- SOL: 7JCf5m3TiHmYKZVr6jCu1KeZVtb9Y1jRMQDU69p5ARnu
- please ask if you want to donate any other coins.
@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "vertical_logo_x1.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "vertical_logo_x2.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "vertical_logo_x3.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

+2 -2
View File
@@ -74,7 +74,7 @@ struct ContentView: View {
}
}
@ViewBuilder func allViews() -> some View {
func allViews() -> some View {
ZStack {
let showCallArea = chatModel.activeCall != nil && chatModel.activeCall?.callState != .waitCapabilities && chatModel.activeCall?.callState != .invitationAccepted
// contentView() has to be in a single branch, so that enabling authentication doesn't trigger re-rendering and close settings.
@@ -209,7 +209,7 @@ struct ContentView: View {
}
}
@ViewBuilder private func activeCallInteractiveArea(_ call: Call) -> some View {
private func activeCallInteractiveArea(_ call: Call) -> some View {
HStack {
Text(call.contact.displayName).font(.body).foregroundColor(.white)
Spacer()
-19
View File
@@ -1413,22 +1413,6 @@ enum NotificationsMode: String, Decodable, SelectableItem {
static var values: [NotificationsMode] = [.instant, .periodic, .off]
}
enum PrivacyChatListOpenLinksMode: String, CaseIterable, Codable, RawRepresentable, Identifiable {
case yes
case no
case ask
var id: Self { self }
var text: LocalizedStringKey {
switch self {
case .yes: return "Yes"
case .no: return "No"
case .ask: return "Ask"
}
}
}
struct RemoteCtrlInfo: Decodable {
var remoteCtrlId: Int64
var ctrlDeviceName: String
@@ -1941,7 +1925,6 @@ struct AppSettings: Codable, Equatable {
var privacyAskToApproveRelays: Bool? = nil
var privacyAcceptImages: Bool? = nil
var privacyLinkPreviews: Bool? = nil
var privacyChatListOpenLinks: PrivacyChatListOpenLinksMode? = nil
var privacyShowChatPreviews: Bool? = nil
var privacySaveLastDraft: Bool? = nil
var privacyProtectScreen: Bool? = nil
@@ -1977,7 +1960,6 @@ struct AppSettings: Codable, Equatable {
if privacyAskToApproveRelays != def.privacyAskToApproveRelays { empty.privacyAskToApproveRelays = privacyAskToApproveRelays }
if privacyAcceptImages != def.privacyAcceptImages { empty.privacyAcceptImages = privacyAcceptImages }
if privacyLinkPreviews != def.privacyLinkPreviews { empty.privacyLinkPreviews = privacyLinkPreviews }
if privacyChatListOpenLinks != def.privacyChatListOpenLinks { empty.privacyChatListOpenLinks = privacyChatListOpenLinks }
if privacyShowChatPreviews != def.privacyShowChatPreviews { empty.privacyShowChatPreviews = privacyShowChatPreviews }
if privacySaveLastDraft != def.privacySaveLastDraft { empty.privacySaveLastDraft = privacySaveLastDraft }
if privacyProtectScreen != def.privacyProtectScreen { empty.privacyProtectScreen = privacyProtectScreen }
@@ -2014,7 +1996,6 @@ struct AppSettings: Codable, Equatable {
privacyAskToApproveRelays: true,
privacyAcceptImages: true,
privacyLinkPreviews: true,
privacyChatListOpenLinks: .ask,
privacyShowChatPreviews: true,
privacySaveLastDraft: true,
privacyProtectScreen: false,
@@ -467,7 +467,7 @@ struct ActiveCallOverlay: View {
.disabled(call.initialCallType == .audio && client.activeCall?.peerHasOldVersion == true)
}
@ViewBuilder private func flipCameraButton() -> some View {
private func flipCameraButton() -> some View {
controlButton(call, "arrow.triangle.2.circlepath", padding: 12) {
Task {
if await WebRTCClient.isAuthorized(for: .video) {
@@ -477,11 +477,11 @@ struct ActiveCallOverlay: View {
}
}
@ViewBuilder private func controlButton(_ call: Call, _ imageName: String, padding: CGFloat, _ perform: @escaping () -> Void) -> some View {
private func controlButton(_ call: Call, _ imageName: String, padding: CGFloat, _ perform: @escaping () -> Void) -> some View {
callButton(imageName, call.peerMediaSources.hasVideo ? Color.black.opacity(0.2) : Color.white.opacity(0.2), padding: padding, perform)
}
@ViewBuilder private func audioDevicePickerButton() -> some View {
private func audioDevicePickerButton() -> some View {
AudioDevicePicker()
.opacity(0.8)
.scaleEffect(2)
@@ -50,7 +50,7 @@ struct CICallItemView: View {
Image(systemName: "phone.connection").foregroundColor(.green)
}
@ViewBuilder private func endedCallIcon(_ sent: Bool) -> some View {
private func endedCallIcon(_ sent: Bool) -> some View {
HStack {
Image(systemName: "phone.down")
Text(durationText(duration)).foregroundColor(theme.colors.secondary)
@@ -60,16 +60,16 @@ struct CICallItemView: View {
@ViewBuilder private func acceptCallButton() -> some View {
if case let .direct(contact) = chat.chatInfo {
Button {
if let invitation = m.callInvitations[contact.id] {
CallController.shared.answerCall(invitation: invitation)
logger.debug("acceptCallButton call answered")
} else {
AlertManager.shared.showAlertMsg(title: "Call already ended!")
}
} label: {
Label("Answer call", systemImage: "phone.arrow.down.left")
}
Label("Answer call", systemImage: "phone.arrow.down.left")
.foregroundColor(theme.colors.primary)
.simultaneousGesture(TapGesture().onEnded {
if let invitation = m.callInvitations[contact.id] {
CallController.shared.answerCall(invitation: invitation)
logger.debug("acceptCallButton call answered")
} else {
AlertManager.shared.showAlertMsg(title: "Call already ended!")
}
})
} else {
Image(systemName: "phone.arrow.down.left").foregroundColor(theme.colors.secondary)
}
@@ -26,9 +26,9 @@ struct CIFeaturePreferenceView: View {
allowed != .no && ct.allowsFeature(feature) && !ct.userAllowsFeature(feature) {
let setParam = feature == .timedMessages && ct.mergedPreferences.timedMessages.userPreference.preference.ttl == nil
featurePreferenceView(acceptText: setParam ? "Set 1 day" : "Accept")
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
allowFeatureToContact(ct, feature, param: setParam ? 86400 : nil)
}
})
} else {
featurePreferenceView()
}
@@ -19,42 +19,42 @@ struct CIFileView: View {
var body: some View {
if smallViewSize != nil {
fileIndicator()
.onTapGesture(perform: fileAction)
.simultaneousGesture(TapGesture().onEnded(fileAction))
} else {
let metaReserve = edited
? " "
: " "
Button(action: fileAction) {
HStack(alignment: .bottom, spacing: 6) {
fileIndicator()
.padding(.top, 5)
.padding(.bottom, 3)
if let file = file {
let prettyFileSize = ByteCountFormatter.string(fromByteCount: file.fileSize, countStyle: .binary)
VStack(alignment: .leading, spacing: 2) {
Text(file.fileName)
.lineLimit(1)
.multilineTextAlignment(.leading)
.foregroundColor(theme.colors.onBackground)
Text(prettyFileSize + metaReserve)
.font(.caption)
.lineLimit(1)
.multilineTextAlignment(.leading)
.foregroundColor(theme.colors.secondary)
}
} else {
Text(metaReserve)
HStack(alignment: .bottom, spacing: 6) {
fileIndicator()
.padding(.top, 5)
.padding(.bottom, 3)
if let file = file {
let prettyFileSize = ByteCountFormatter.string(fromByteCount: file.fileSize, countStyle: .binary)
VStack(alignment: .leading, spacing: 2) {
Text(file.fileName)
.lineLimit(1)
.multilineTextAlignment(.leading)
.foregroundColor(theme.colors.onBackground)
Text(prettyFileSize + metaReserve)
.font(.caption)
.lineLimit(1)
.multilineTextAlignment(.leading)
.foregroundColor(theme.colors.secondary)
}
} else {
Text(metaReserve)
}
.padding(.top, 4)
.padding(.bottom, 6)
.padding(.leading, 10)
.padding(.trailing, 12)
}
.padding(.top, 4)
.padding(.bottom, 6)
.padding(.leading, 10)
.padding(.trailing, 12)
.simultaneousGesture(TapGesture().onEnded(fileAction))
.disabled(!itemInteractive)
}
}
@inline(__always)
private var itemInteractive: Bool {
if let file = file {
switch (file.fileStatus) {
@@ -84,12 +84,12 @@ struct CIGroupInvitationView: View {
}
if action {
v.onTapGesture {
v.simultaneousGesture(TapGesture().onEnded {
inProgress = true
joinGroup(groupInvitation.groupId) {
await MainActor.run { inProgress = false }
}
}
})
.disabled(inProgress)
} else {
v
@@ -31,7 +31,9 @@ struct CIImageView: View {
.if(!smallView) { view in
view.modifier(PrivacyBlur(blurred: $blurred))
}
.onTapGesture { showFullScreenImage = true }
.if(!blurred) { v in
v.simultaneousGesture(TapGesture().onEnded { showFullScreenImage = true })
}
.onChange(of: m.activeCallViewIsCollapsed) { _ in
showFullScreenImage = false
}
@@ -43,7 +45,7 @@ struct CIImageView: View {
imageView(preview).modifier(PrivacyBlur(blurred: $blurred))
}
}
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
if let file = file {
switch file.fileStatus {
case .rcvInvitation, .rcvAborted:
@@ -80,7 +82,7 @@ struct CIImageView: View {
default: ()
}
}
}
})
}
}
.onDisappear {
@@ -24,7 +24,7 @@ struct CIInvalidJSONView: View {
.padding(.vertical, 6)
.background(Color(uiColor: .tertiarySystemGroupedBackground))
.textSelection(.disabled)
.onTapGesture { showJSON = true }
.simultaneousGesture(TapGesture().onEnded { showJSON = true })
.appSheet(isPresented: $showJSON) {
invalidJSONView(dataToString(json))
}
@@ -33,7 +33,7 @@ struct CIInvalidJSONView: View {
func invalidJSONView(_ json: String) -> some View {
VStack(alignment: .leading, spacing: 16) {
Button {
Button { // this is used in the sheet, Button works here
showShareSheet(items: [json])
} label: {
Image(systemName: "square.and.arrow.up")
@@ -21,15 +21,15 @@ struct CILinkView: View {
.resizable()
.scaledToFit()
.modifier(PrivacyBlur(blurred: $blurred))
.if(!blurred) { v in
v.simultaneousGesture(TapGesture().onEnded {
openBrowserAlert(uri: linkPreview.uri)
})
}
}
VStack(alignment: .leading, spacing: 6) {
Text(linkPreview.title)
.lineLimit(3)
// if linkPreview.description != "" {
// Text(linkPreview.description)
// .font(.subheadline)
// .lineLimit(12)
// }
Text(linkPreview.uri.absoluteString)
.font(.caption)
.lineLimit(1)
@@ -37,10 +37,32 @@ struct CILinkView: View {
}
.padding(.horizontal, 12)
.frame(maxWidth: .infinity, alignment: .leading)
.simultaneousGesture(TapGesture().onEnded {
openBrowserAlert(uri: linkPreview.uri)
})
}
}
}
func openBrowserAlert(uri: URL) {
showAlert(
NSLocalizedString("Open link?", comment: "alert title"),
message: uri.absoluteString,
actions: {[
UIAlertAction(
title: NSLocalizedString("Cancel", comment: "alert action"),
style: .default,
handler: { _ in }
),
UIAlertAction(
title: NSLocalizedString("Open", comment: "alert action"),
style: .default,
handler: { _ in UIApplication.shared.open(uri) }
)
]}
)
}
struct LargeLinkPreview_Previews: PreviewProvider {
static var previews: some View {
let preview = LinkPreview(
@@ -20,11 +20,11 @@ struct CIMemberCreatedContactView: View {
case let .groupRcv(groupMember):
if let contactId = groupMember.memberContactId {
memberCreatedContactView(openText: "Open")
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
ItemsModel.shared.loadOpenChat("@\(contactId)") {
dismissAllSheets(animated: true)
}
}
})
} else {
memberCreatedContactView()
}
@@ -15,7 +15,7 @@ struct CIMetaView: View {
@Environment(\.showTimestamp) var showTimestamp: Bool
var chatItem: ChatItem
var metaColor: Color
var paleMetaColor = Color(UIColor.tertiaryLabel)
var paleMetaColor = Color(uiColor: .tertiaryLabel)
var showStatus = true
var showEdited = true
var invertedMaterial = false
@@ -152,11 +152,13 @@ func ciMetaText(
return r.font(.caption)
}
@inline(__always)
private func statusIconText(_ icon: String, _ color: Color?) -> Text {
colored(Text(Image(systemName: icon)), color)
}
// Applying `foregroundColor(nil)` breaks `.invertedForegroundStyle` modifier
@inline(__always)
private func colored(_ t: Text, _ color: Color?) -> Text {
if let color {
t.foregroundColor(color)
@@ -68,7 +68,7 @@ struct CIRcvDecryptionError: View {
}
}
@ViewBuilder private func viewBody() -> some View {
private func viewBody() -> some View {
Group {
if case let .direct(contact) = chat.chatInfo,
let contactStats = contact.activeConn?.connectionStats {
@@ -133,7 +133,7 @@ struct CIRcvDecryptionError: View {
CIMetaView(chat: chat, chatItem: chatItem, metaColor: theme.colors.secondary)
.padding(.horizontal, 12)
}
.onTapGesture(perform: { onClick() })
.simultaneousGesture(TapGesture().onEnded(onClick))
.padding(.vertical, 6)
.textSelection(.disabled)
}
@@ -151,7 +151,7 @@ struct CIRcvDecryptionError: View {
CIMetaView(chat: chat, chatItem: chatItem, metaColor: theme.colors.secondary)
.padding(.horizontal, 12)
}
.onTapGesture(perform: { onClick() })
.simultaneousGesture(TapGesture().onEnded(onClick))
.padding(.vertical, 6)
.textSelection(.disabled)
}
@@ -47,57 +47,57 @@ struct CIVideoView: View {
let file = chatItem.file
ZStack(alignment: smallView ? .topLeading : .center) {
ZStack(alignment: .topLeading) {
if let file = file, let preview = preview, let decrypted = urlDecrypted, smallView {
smallVideoView(decrypted, file, preview)
} else if let file = file, let preview = preview, let player = player, let decrypted = urlDecrypted {
videoView(player, decrypted, file, preview, duration)
} else if let file = file, let defaultPreview = preview, file.loaded && urlDecrypted == nil, smallView {
smallVideoViewEncrypted(file, defaultPreview)
} else if let file = file, let defaultPreview = preview, file.loaded && urlDecrypted == nil {
videoViewEncrypted(file, defaultPreview, duration)
} else if let preview, let file {
Group { if smallView { smallViewImageView(preview, file) } else { imageView(preview) } }
.onTapGesture {
switch file.fileStatus {
case .rcvInvitation, .rcvAborted:
receiveFileIfValidSize(file: file, receiveFile: receiveFile)
case .rcvAccepted:
switch file.fileProtocol {
case .xftp:
AlertManager.shared.showAlertMsg(
title: "Waiting for video",
message: "Video will be received when your contact completes uploading it."
)
case .smp:
AlertManager.shared.showAlertMsg(
title: "Waiting for video",
message: "Video will be received when your contact is online, please wait or check later!"
)
case .local: ()
}
case .rcvTransfer: () // ?
case .rcvComplete: () // ?
case .rcvCancelled: () // TODO
default: ()
}
if let file, let preview {
if let urlDecrypted {
if smallView {
smallVideoView(urlDecrypted, file, preview)
} else if let player {
videoView(player, urlDecrypted, file, preview, duration)
}
} else if file.loaded {
if smallView {
smallVideoViewEncrypted(file, preview)
} else {
videoViewEncrypted(file, preview, duration)
}
} else {
Group { if smallView { smallViewImageView(preview, file) } else { imageView(preview) } }
.simultaneousGesture(TapGesture().onEnded {
switch file.fileStatus {
case .rcvInvitation, .rcvAborted:
receiveFileIfValidSize(file: file, receiveFile: receiveFile)
case .rcvAccepted:
switch file.fileProtocol {
case .xftp:
AlertManager.shared.showAlertMsg(
title: "Waiting for video",
message: "Video will be received when your contact completes uploading it."
)
case .smp:
AlertManager.shared.showAlertMsg(
title: "Waiting for video",
message: "Video will be received when your contact is online, please wait or check later!"
)
case .local: ()
}
case .rcvTransfer: () // ?
case .rcvComplete: () // ?
case .rcvCancelled: () // TODO
default: ()
}
})
}
}
if !smallView {
durationProgress()
}
}
if !blurred, let file, showDownloadButton(file.fileStatus) {
if !smallView {
Button {
receiveFileIfValidSize(file: file, receiveFile: receiveFile)
} label: {
playPauseIcon("play.fill")
}
} else if !file.showStatusIconInSmallView {
if !smallView || !file.showStatusIconInSmallView {
playPauseIcon("play.fill")
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
receiveFileIfValidSize(file: file, receiveFile: receiveFile)
}
})
}
}
}
@@ -151,27 +151,26 @@ struct CIVideoView: View {
ZStack(alignment: .center) {
let canBePlayed = !chatItem.chatDir.sent || file.fileStatus == CIFileStatus.sndComplete || (file.fileStatus == .sndStored && file.fileProtocol == .local)
imageView(defaultPreview)
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
decrypt(file: file) {
showFullScreenPlayer = urlDecrypted != nil
}
}
})
.onChange(of: m.activeCallViewIsCollapsed) { _ in
showFullScreenPlayer = false
}
if !blurred {
if !decryptionInProgress {
Button {
decrypt(file: file) {
if urlDecrypted != nil {
videoPlaying = true
player?.play()
playPauseIcon(canBePlayed ? "play.fill" : "play.slash")
.simultaneousGesture(TapGesture().onEnded {
decrypt(file: file) {
if urlDecrypted != nil {
videoPlaying = true
player?.play()
}
}
}
} label: {
playPauseIcon(canBePlayed ? "play.fill" : "play.slash")
}
.disabled(!canBePlayed)
})
.disabled(!canBePlayed)
} else {
videoDecryptionProgress()
}
@@ -194,29 +193,30 @@ struct CIVideoView: View {
}
}
.modifier(PrivacyBlur(enabled: !videoPlaying, blurred: $blurred))
.onTapGesture {
switch player.timeControlStatus {
case .playing:
player.pause()
videoPlaying = false
case .paused:
if canBePlayed {
showFullScreenPlayer = true
.if(!blurred) { v in
v.simultaneousGesture(TapGesture().onEnded {
switch player.timeControlStatus {
case .playing:
player.pause()
videoPlaying = false
case .paused:
if canBePlayed {
showFullScreenPlayer = true
}
default: ()
}
default: ()
}
})
}
.onChange(of: m.activeCallViewIsCollapsed) { _ in
showFullScreenPlayer = false
}
if !videoPlaying && !blurred {
Button {
m.stopPreviousRecPlay = url
player.play()
} label: {
playPauseIcon(canBePlayed ? "play.fill" : "play.slash")
}
.disabled(!canBePlayed)
playPauseIcon(canBePlayed ? "play.fill" : "play.slash")
.simultaneousGesture(TapGesture().onEnded {
m.stopPreviousRecPlay = url
player.play()
})
.disabled(!canBePlayed)
}
}
fileStatusIcon()
@@ -235,7 +235,7 @@ struct CIVideoView: View {
return ZStack(alignment: .topLeading) {
let canBePlayed = !chatItem.chatDir.sent || file.fileStatus == CIFileStatus.sndComplete || (file.fileStatus == .sndStored && file.fileProtocol == .local)
smallViewImageView(preview, file)
.onTapGesture {
.onTapGesture { // this is shown in chat list, where onTapGesture works
decrypt(file: file) {
showFullScreenPlayer = urlDecrypted != nil
}
@@ -256,7 +256,7 @@ struct CIVideoView: View {
private func smallVideoView(_ url: URL, _ file: CIFile, _ preview: UIImage) -> some View {
return ZStack(alignment: .topLeading) {
smallViewImageView(preview, file)
.onTapGesture {
.onTapGesture { // this is shown in chat list, where onTapGesture works
showFullScreenPlayer = true
}
.onChange(of: m.activeCallViewIsCollapsed) { _ in
@@ -354,14 +354,14 @@ struct CIVideoView: View {
case .sndCancelled: fileIcon("xmark", 10, 13)
case let .sndError(sndFileError):
fileIcon("xmark", 10, 13)
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
showFileErrorAlert(sndFileError)
}
})
case let .sndWarning(sndFileError):
fileIcon("exclamationmark.triangle.fill", 10, 13)
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
showFileErrorAlert(sndFileError, temporary: true)
}
})
case .rcvInvitation: fileIcon("arrow.down", 10, 13)
case .rcvAccepted: fileIcon("ellipsis", 14, 11)
case let .rcvTransfer(rcvProgress, rcvTotal):
@@ -375,14 +375,14 @@ struct CIVideoView: View {
case .rcvCancelled: fileIcon("xmark", 10, 13)
case let .rcvError(rcvFileError):
fileIcon("xmark", 10, 13)
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
showFileErrorAlert(rcvFileError)
}
})
case let .rcvWarning(rcvFileError):
fileIcon("exclamationmark.triangle.fill", 10, 13)
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
showFileErrorAlert(rcvFileError, temporary: true)
}
})
case .invalid: fileIcon("questionmark", 10, 13)
}
}
@@ -429,7 +429,7 @@ struct CIVideoView: View {
Color.black.edgesIgnoringSafeArea(.all)
VideoPlayer(player: fullPlayer)
.overlay(alignment: .topLeading, content: {
Button(action: { showFullScreenPlayer = false },
Button(action: { showFullScreenPlayer = false }, // this is used in full screen player, Button works here
label: {
Image(systemName: "multiply")
.resizable()
@@ -168,14 +168,14 @@ struct VoiceMessagePlayer: View {
case .sndCancelled: playbackButton()
case let .sndError(sndFileError):
fileStatusIcon("multiply", 14)
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
showFileErrorAlert(sndFileError)
}
})
case let .sndWarning(sndFileError):
fileStatusIcon("exclamationmark.triangle.fill", 16)
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
showFileErrorAlert(sndFileError, temporary: true)
}
})
case .rcvInvitation: downloadButton(recordingFile, "play.fill")
case .rcvAccepted: loadingIcon()
case .rcvTransfer: loadingIcon()
@@ -184,14 +184,14 @@ struct VoiceMessagePlayer: View {
case .rcvCancelled: playPauseIcon("play.fill", Color(uiColor: .tertiaryLabel))
case let .rcvError(rcvFileError):
fileStatusIcon("multiply", 14)
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
showFileErrorAlert(rcvFileError)
}
})
case let .rcvWarning(rcvFileError):
fileStatusIcon("exclamationmark.triangle.fill", 16)
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
showFileErrorAlert(rcvFileError, temporary: true)
}
})
case .invalid: playPauseIcon("play.fill", Color(uiColor: .tertiaryLabel))
}
} else {
@@ -255,59 +255,29 @@ struct VoiceMessagePlayer: View {
}
}
@ViewBuilder private func playbackButton() -> some View {
if sizeMultiplier != 1 {
switch playbackState {
case .noPlayback:
playPauseIcon("play.fill", theme.colors.primary)
.onTapGesture {
if let recordingSource = getLoadedFileSource(recordingFile) {
startPlayback(recordingSource)
}
}
case .playing:
playPauseIcon("pause.fill", theme.colors.primary)
.onTapGesture {
audioPlayer?.pause()
playbackState = .paused
notifyStateChange()
}
case .paused:
playPauseIcon("play.fill", theme.colors.primary)
.onTapGesture {
audioPlayer?.play()
playbackState = .playing
notifyStateChange()
}
}
} else {
switch playbackState {
case .noPlayback:
Button {
private func playbackButton() -> some View {
let icon = switch playbackState {
case .noPlayback: "play.fill"
case .playing: "pause.fill"
case .paused: "play.fill"
}
return playPauseIcon(icon, theme.colors.primary)
.simultaneousGesture(TapGesture().onEnded { _ in
switch playbackState {
case .noPlayback:
if let recordingSource = getLoadedFileSource(recordingFile) {
startPlayback(recordingSource)
}
} label: {
playPauseIcon("play.fill", theme.colors.primary)
}
case .playing:
Button {
case .playing:
audioPlayer?.pause()
playbackState = .paused
notifyStateChange()
} label: {
playPauseIcon("pause.fill", theme.colors.primary)
}
case .paused:
Button {
case .paused:
audioPlayer?.play()
playbackState = .playing
notifyStateChange()
} label: {
playPauseIcon("play.fill", theme.colors.primary)
}
}
}
})
}
private func playPauseIcon(_ image: String, _ color: Color/* = .accentColor*/) -> some View {
@@ -329,28 +299,14 @@ struct VoiceMessagePlayer: View {
}
private func downloadButton(_ recordingFile: CIFile, _ icon: String) -> some View {
Group {
if sizeMultiplier != 1 {
playPauseIcon(icon, theme.colors.primary)
.onTapGesture {
Task {
if let user = chatModel.currentUser {
await receiveFile(user: user, fileId: recordingFile.fileId)
}
}
playPauseIcon(icon, theme.colors.primary)
.simultaneousGesture(TapGesture().onEnded {
Task {
if let user = chatModel.currentUser {
await receiveFile(user: user, fileId: recordingFile.fileId)
}
} else {
Button {
Task {
if let user = chatModel.currentUser {
await receiveFile(user: user, fileId: recordingFile.fileId)
}
}
} label: {
playPauseIcon(icon, theme.colors.primary)
}
}
}
})
}
func notifyStateChange() {
@@ -430,6 +386,7 @@ struct VoiceMessagePlayer: View {
}
}
@inline(__always)
func voiceMessageSizeBasedOnSquareSize(_ squareSize: CGFloat) -> CGFloat {
let squareToCircleRatio = 0.935
return squareSize + squareSize * (1 - squareToCircleRatio)
@@ -446,10 +403,12 @@ class VoiceItemState {
self.playbackTime = playbackTime
}
@inline(__always)
static func id(_ chat: Chat, _ chatItem: ChatItem) -> String {
"\(chat.id) \(chatItem.id)"
}
@inline(__always)
static func id(_ chatInfo: ChatInfo, _ chatItem: ChatItem) -> String {
"\(chatInfo.id) \(chatItem.id)"
}
@@ -23,8 +23,6 @@ struct FramedItemView: View {
@State private var useWhiteMetaColor: Bool = false
@State var showFullScreenImage = false
@Binding var allowMenu: Bool
@State private var showSecrets = false
@State private var showQuoteSecrets = false
@State private var showFullscreenGallery: Bool = false
var body: some View {
@@ -57,7 +55,7 @@ struct FramedItemView: View {
if let qi = chatItem.quotedItem {
ciQuoteView(qi)
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
if let ci = ItemsModel.shared.reversedChatItems.first(where: { $0.id == qi.itemId }) {
withAnimation {
scrollToItemId(ci.id)
@@ -67,7 +65,7 @@ struct FramedItemView: View {
} else {
showQuotedItemDoesNotExistAlert()
}
}
})
} else if let itemForwarded = chatItem.meta.itemForwarded {
framedItemHeader(icon: "arrowshape.turn.up.forward", caption: Text(itemForwarded.text(chat.chatInfo.chatType)).italic(), pad: true)
}
@@ -89,19 +87,19 @@ struct FramedItemView: View {
.overlay(DetermineWidth())
.accessibilityLabel("")
}
}
}
.background { chatItemFrameColorMaybeImageOrVideo(chatItem, theme).modifier(ChatTailPadding()) }
.onPreferenceChange(DetermineWidth.Key.self) { msgWidth = $0 }
if let (title, text) = chatItem.meta.itemStatus.statusInfo {
v.onTapGesture {
v.simultaneousGesture(TapGesture().onEnded {
AlertManager.shared.showAlert(
Alert(
title: Text(title),
message: Text(text)
)
)
}
})
} else {
v
}
@@ -159,7 +157,7 @@ struct FramedItemView: View {
case let .file(text):
ciFileView(chatItem, text)
case let .report(text, reason):
ciMsgContentView(chatItem, Text(text.isEmpty ? reason.text : "\(reason.text): ").italic().foregroundColor(.red))
ciMsgContentView(chatItem, txtPrefix: reason.attrString)
case let .link(_, preview):
CILinkView(linkPreview: preview)
ciMsgContentView(chatItem)
@@ -203,6 +201,7 @@ struct FramedItemView: View {
}
@ViewBuilder private func ciQuoteView(_ qi: CIQuote) -> some View {
let backgroundColor = chatItemFrameContextColor(chatItem, theme)
let v = ZStack(alignment: .topTrailing) {
switch (qi.content) {
case let .image(_, image):
@@ -244,7 +243,8 @@ struct FramedItemView: View {
// if enable this always, size of the framed voice message item will be incorrect after end of playback
.overlay { if case .voice = chatItem.content.msgContent {} else { DetermineWidth() } }
.frame(minWidth: msgWidth, alignment: .leading)
.background(chatItemFrameContextColor(chatItem, theme))
.background(backgroundColor)
.environment(\.containerBackground, UIColor(backgroundColor))
if let mediaWidth = maxMediaWidth(), mediaWidth < maxWidth {
v.frame(maxWidth: mediaWidth, alignment: .leading)
} else {
@@ -270,14 +270,12 @@ struct FramedItemView: View {
.padding(.top, 6)
.padding(.horizontal, 12)
}
@inline(__always)
private func ciQuotedMsgTextView(_ qi: CIQuote, lines: Int) -> some View {
toggleSecrets(qi.formattedText, $showQuoteSecrets,
MsgContentView(chat: chat, text: qi.text, formattedText: qi.formattedText, showSecrets: showQuoteSecrets)
.lineLimit(lines)
.font(.subheadline)
.padding(.bottom, 6)
)
MsgContentView(chat: chat, text: qi.text, formattedText: qi.formattedText, textStyle: .subheadline)
.lineLimit(lines)
.padding(.bottom, 6)
}
private func ciQuoteIconView(_ image: String) -> some View {
@@ -297,21 +295,22 @@ struct FramedItemView: View {
}
}
@ViewBuilder private func ciMsgContentView(_ ci: ChatItem, _ txtPrefix: Text? = nil) -> some View {
@ViewBuilder private func ciMsgContentView(_ ci: ChatItem, txtPrefix: NSAttributedString? = nil) -> some View {
let text = ci.meta.isLive ? ci.content.msgContent?.text ?? ci.text : ci.text
let rtl = isRightToLeft(text)
let ft = text == "" ? [] : ci.formattedText
let v = toggleSecrets(ft, $showSecrets, MsgContentView(
let v = MsgContentView(
chat: chat,
text: text,
formattedText: ft,
textStyle: .body,
meta: ci.meta,
mentions: ci.mentions,
userMemberId: chat.chatInfo.groupInfo?.membership.memberId,
rightToLeft: rtl,
showSecrets: showSecrets,
prefix: txtPrefix
))
)
.environment(\.containerBackground, UIColor(chatItemFrameColor(ci, theme)))
.multilineTextAlignment(rtl ? .trailing : .leading)
.padding(.vertical, 6)
.padding(.horizontal, 12)
@@ -351,14 +350,6 @@ struct FramedItemView: View {
}
}
@ViewBuilder func toggleSecrets<V: View>(_ ft: [FormattedText]?, _ showSecrets: Binding<Bool>, _ v: V) -> some View {
if let ft = ft, ft.contains(where: { $0.isSecret }) {
v.onTapGesture { showSecrets.wrappedValue.toggle() }
} else {
v
}
}
func isRightToLeft(_ s: String) -> Bool {
if let lang = CFStringTokenizerCopyBestStringLanguage(s as CFString, CFRange(location: 0, length: min(s.count, 80))) {
return NSLocale.characterDirection(forLanguage: lang as String) == .rightToLeft
@@ -126,7 +126,7 @@ struct FullScreenMediaView: View {
.scaledToFit()
}
}
.onTapGesture { showView = false }
.onTapGesture { showView = false } // this is used in full screen view, onTapGesture works
}
private func videoView( _ player: AVPlayer, _ url: URL) -> some View {
@@ -71,7 +71,7 @@ struct CIMsgError: View {
.padding(.vertical, 6)
.background { chatItemFrameColor(chatItem, theme).modifier(ChatTailPadding()) }
.textSelection(.disabled)
.onTapGesture(perform: onTap)
.simultaneousGesture(TapGesture().onEnded(onTap))
}
}
@@ -11,53 +11,74 @@ import SimpleXChat
let uiLinkColor = UIColor(red: 0, green: 0.533, blue: 1, alpha: 1)
private let noTyping = Text(verbatim: " ")
private let typingIndicators: [Text] = [
(typing(.black) + typing() + typing()),
(typing(.bold) + typing(.black) + typing()),
(typing() + typing(.bold) + typing(.black)),
(typing() + typing() + typing(.bold))
]
private func typing(_ w: Font.Weight = .light) -> Text {
Text(verbatim: ".").fontWeight(w)
private func typing(_ theme: AppTheme, _ descr: UIFontDescriptor, _ ws: [UIFont.Weight]) -> NSMutableAttributedString {
let res = NSMutableAttributedString()
for w in ws {
res.append(NSAttributedString(string: ".", attributes: [
.font: UIFont.monospacedSystemFont(ofSize: descr.pointSize, weight: w),
.kern: -2 as NSNumber,
.foregroundColor: UIColor(theme.colors.secondary)
]))
}
return res
}
struct MsgContentView: View {
@ObservedObject var chat: Chat
@Environment(\.showTimestamp) var showTimestamp: Bool
@Environment(\.containerBackground) var containerBackground: UIColor
@EnvironmentObject var theme: AppTheme
var text: String
var formattedText: [FormattedText]? = nil
var textStyle: UIFont.TextStyle
var sender: String? = nil
var meta: CIMeta? = nil
var mentions: [String: CIMention]? = nil
var userMemberId: String? = nil
var rightToLeft = false
var showSecrets: Bool
var prefix: Text? = nil
var prefix: NSAttributedString? = nil
@State private var showSecrets: Set<Int> = []
@State private var typingIdx = 0
@State private var timer: Timer?
@State private var typingIndicators: [NSAttributedString] = []
@State private var noTyping = NSAttributedString(string: " ")
@State private var phase: CGFloat = 0
@AppStorage(DEFAULT_SHOW_SENT_VIA_RPOXY) private var showSentViaProxy = false
var body: some View {
let v = msgContentView()
if meta?.isLive == true {
msgContentView()
.onAppear { switchTyping() }
v.onAppear {
let descr = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
noTyping = NSAttributedString(string: " ", attributes: [
.font: UIFont.monospacedSystemFont(ofSize: descr.pointSize, weight: .regular),
.kern: -2 as NSNumber,
.foregroundColor: UIColor(theme.colors.secondary)
])
switchTyping()
}
.onDisappear(perform: stopTyping)
.onChange(of: meta?.isLive, perform: switchTyping)
.onChange(of: meta?.recent, perform: switchTyping)
} else {
msgContentView()
v
}
}
private func switchTyping(_: Bool? = nil) {
if let meta = meta, meta.isLive && meta.recent {
if typingIndicators.isEmpty {
let descr = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
typingIndicators = [
typing(theme, descr, [.black, .light, .light]),
typing(theme, descr, [.bold, .black, .light]),
typing(theme, descr, [.light, .bold, .black]),
typing(theme, descr, [.light, .light, .bold])
]
}
timer = timer ?? Timer.scheduledTimer(withTimeInterval: 0.25, repeats: true) { _ in
typingIdx = (typingIdx + 1) % typingIndicators.count
typingIdx = typingIdx + 1
}
} else {
stopTyping()
@@ -67,119 +88,276 @@ struct MsgContentView: View {
private func stopTyping() {
timer?.invalidate()
timer = nil
typingIdx = 0
}
private func msgContentView() -> Text {
var v = messageText(text, formattedText, sender, mentions: mentions, userMemberId: userMemberId, showSecrets: showSecrets, secondaryColor: theme.colors.secondary, prefix: prefix)
@inline(__always)
private func msgContentView() -> some View {
let r = messageText(text, formattedText, textStyle: textStyle, sender: sender, mentions: mentions, userMemberId: userMemberId, showSecrets: showSecrets, backgroundColor: containerBackground, prefix: prefix)
let s = r.string
let t: Text
if let mt = meta {
if mt.isLive {
v = v + typingIndicator(mt.recent)
s.append(typingIndicator(mt.recent))
}
v = v + reserveSpaceForMeta(mt)
t = Text(AttributedString(s)) + reserveSpaceForMeta(mt)
} else {
t = Text(AttributedString(s))
}
return v
return msgTextResultView(r, t, showSecrets: $showSecrets)
}
private func typingIndicator(_ recent: Bool) -> Text {
return (recent ? typingIndicators[typingIdx] : noTyping)
.font(.body.monospaced())
.kerning(-2)
.foregroundColor(theme.colors.secondary)
@inline(__always)
private func typingIndicator(_ recent: Bool) -> NSAttributedString {
recent && !typingIndicators.isEmpty
? typingIndicators[typingIdx % 4]
: noTyping
}
@inline(__always)
private func reserveSpaceForMeta(_ mt: CIMeta) -> Text {
(rightToLeft ? textNewLine : Text(verbatim: " ")) + ciMetaText(mt, chatTTL: chat.chatInfo.timedMessagesTTL, encrypted: nil, colorMode: .transparent, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp)
}
}
func messageText(_ text: String, _ formattedText: [FormattedText]?, _ sender: String?, icon: String? = nil, preview: Bool = false, mentions: [String: CIMention]?, userMemberId: String?, showSecrets: Bool, secondaryColor: Color, prefix: Text? = nil) -> Text {
let s = text
var res: Text
if let ft = formattedText, ft.count > 0 && ft.count <= 200 {
res = formatText(ft[0], preview, showSecret: showSecrets, mentions: mentions, userMemberId: userMemberId)
var i = 1
while i < ft.count {
res = res + formatText(ft[i], preview, showSecret: showSecrets, mentions: mentions, userMemberId: userMemberId)
i = i + 1
}
} else {
res = Text(s)
}
if let i = icon {
res = Text(Image(systemName: i)).foregroundColor(secondaryColor) + textSpace + res
}
if let p = prefix {
res = p + res
}
if let s = sender {
let t = Text(s)
return (preview ? t : t.fontWeight(.medium)) + Text(verbatim: ": ") + res
} else {
return res
}
func msgTextResultView(_ r: MsgTextResult, _ t: Text, showSecrets: Binding<Set<Int>>? = nil) -> some View {
t.if(r.hasSecrets, transform: hiddenSecretsView)
.if(r.handleTaps) { $0.overlay(handleTextTaps(r.string, showSecrets: showSecrets)) }
}
private func formatText(_ ft: FormattedText, _ preview: Bool, showSecret: Bool, mentions: [String: CIMention]?, userMemberId: String?) -> Text {
let t = ft.text
if let f = ft.format {
switch (f) {
case .bold: return Text(t).bold()
case .italic: return Text(t).italic()
case .strikeThrough: return Text(t).strikethrough()
case .snippet: return Text(t).font(.body.monospaced())
case .secret: return
showSecret
? Text(t)
: Text(AttributedString(t, attributes: AttributeContainer([
.foregroundColor: UIColor.clear as Any,
.backgroundColor: UIColor.secondarySystemFill as Any
])))
case let .colored(color): return Text(t).foregroundColor(color.uiColor)
case .uri: return linkText(t, t, preview, prefix: "")
case let .simplexLink(linkType, simplexUri, smpHosts):
switch privacySimplexLinkModeDefault.get() {
case .description: return linkText(simplexLinkText(linkType, smpHosts), simplexUri, preview, prefix: "")
case .full: return linkText(t, simplexUri, preview, prefix: "")
case .browser: return linkText(t, simplexUri, preview, prefix: "")
}
case let .mention(memberName):
if let m = mentions?[memberName] {
if let ref = m.memberRef {
let name: String = if let alias = ref.localAlias, alias != "" {
"\(alias) (\(ref.displayName))"
} else {
ref.displayName
@inline(__always)
private func handleTextTaps(_ s: NSAttributedString, showSecrets: Binding<Set<Int>>? = nil) -> some View {
return GeometryReader { g in
Rectangle()
.fill(Color.clear)
.contentShape(Rectangle())
.simultaneousGesture(DragGesture(minimumDistance: 0).onEnded { event in
let t = event.translation
if t.width * t.width + t.height * t.height > 100 { return }
let framesetter = CTFramesetterCreateWithAttributedString(s as CFAttributedString)
let path = CGPath(rect: CGRect(origin: .zero, size: g.size), transform: nil)
let frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, s.length), path, nil)
let point = CGPoint(x: event.location.x, y: g.size.height - event.location.y) // Flip y for UIKit
var index: CFIndex?
if let lines = CTFrameGetLines(frame) as? [CTLine] {
var origins = [CGPoint](repeating: .zero, count: lines.count)
CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), &origins)
for i in 0 ..< lines.count {
let bounds = CTLineGetBoundsWithOptions(lines[i], .useOpticalBounds)
if bounds.offsetBy(dx: origins[i].x, dy: origins[i].y).contains(point) {
index = CTLineGetStringIndexForPosition(lines[i], point)
break
}
}
let tName = mentionText(name)
return m.memberId == userMemberId ? tName.foregroundColor(.accentColor) : tName
} else {
return mentionText(memberName)
}
if let index, let (url, browser) = attributedStringLink(s, for: index) {
if browser {
openBrowserAlert(uri: url)
} else {
UIApplication.shared.open(url)
}
}
})
}
func attributedStringLink(_ s: NSAttributedString, for index: CFIndex) -> (URL, Bool)? {
var linkURL: URL?
var browser: Bool = false
s.enumerateAttributes(in: NSRange(location: 0, length: s.length)) { attrs, range, stop in
if index >= range.location && index < range.location + range.length {
if let url = attrs[linkAttrKey] as? NSURL {
linkURL = url.absoluteURL
browser = attrs[webLinkAttrKey] != nil
} else if let showSecrets, let i = attrs[secretAttrKey] as? Int {
if showSecrets.wrappedValue.contains(i) {
showSecrets.wrappedValue.remove(i)
} else {
showSecrets.wrappedValue.insert(i)
}
}
stop.pointee = true
}
return Text(t)
case .email: return linkText(t, t, preview, prefix: "mailto:")
case .phone: return linkText(t, t.replacingOccurrences(of: " ", with: ""), preview, prefix: "tel:")
}
} else {
return Text(t)
return if let linkURL { (linkURL, browser) } else { nil }
}
}
private func mentionText(_ name: String) -> Text {
Text(verbatim: name.contains(" @") ? "@'\(name)'" : "@\(name)").fontWeight(.semibold)
func hiddenSecretsView<V: View>(_ v: V) -> some View {
v.overlay(
GeometryReader { g in
let size = (g.size.width + g.size.height) / 1.4142
Image("vertical_logo")
.resizable(resizingMode: .tile)
.frame(width: size, height: size)
.rotationEffect(.degrees(45), anchor: .center)
.position(x: g.size.width / 2, y: g.size.height / 2)
.clipped()
.saturation(0.65)
.opacity(0.35)
}
.mask(v)
)
}
private func linkText(_ s: String, _ link: String, _ preview: Bool, prefix: String, color: Color = Color(uiColor: uiLinkColor), uiColor: UIColor = uiLinkColor) -> Text {
preview
? Text(s).foregroundColor(color).underline(color: color)
: Text(AttributedString(s, attributes: AttributeContainer([
.link: NSURL(string: prefix + link) as Any,
.foregroundColor: uiColor as Any
]))).underline()
private let linkAttrKey = NSAttributedString.Key("chat.simplex.app.link")
private let webLinkAttrKey = NSAttributedString.Key("chat.simplex.app.webLink")
private let secretAttrKey = NSAttributedString.Key("chat.simplex.app.secret")
typealias MsgTextResult = (string: NSMutableAttributedString, hasSecrets: Bool, handleTaps: Bool)
func messageText(
_ text: String,
_ formattedText: [FormattedText]?,
textStyle: UIFont.TextStyle = .body,
sender: String?,
preview: Bool = false,
mentions: [String: CIMention]?,
userMemberId: String?,
showSecrets: Set<Int>?,
backgroundColor: UIColor,
prefix: NSAttributedString? = nil
) -> MsgTextResult {
let res = NSMutableAttributedString()
let descr = UIFontDescriptor.preferredFontDescriptor(withTextStyle: textStyle)
let font = UIFont.preferredFont(forTextStyle: textStyle)
let plain: [NSAttributedString.Key: Any] = [
.font: font,
.foregroundColor: UIColor.label
]
let secretColor = backgroundColor.withAlphaComponent(1)
var link: [NSAttributedString.Key: Any]?
var hasSecrets = false
var handleTaps = false
if let sender {
if preview {
res.append(NSAttributedString(string: sender + ": ", attributes: plain))
} else {
var attrs = plain
attrs[.font] = UIFont(descriptor: descr.addingAttributes([.traits: [UIFontDescriptor.TraitKey.weight: UIFont.Weight.medium]]), size: descr.pointSize)
res.append(NSAttributedString(string: sender, attributes: attrs))
res.append(NSAttributedString(string: ": ", attributes: plain))
}
}
if let prefix {
res.append(prefix)
}
if let fts = formattedText, fts.count > 0 {
var bold: UIFont?
var italic: UIFont?
var snippet: UIFont?
var mention: UIFont?
var secretIdx: Int = 0
for ft in fts {
var t = ft.text
var attrs = plain
switch (ft.format) {
case .bold:
bold = bold ?? UIFont(descriptor: descr.addingAttributes([.traits: [UIFontDescriptor.TraitKey.weight: UIFont.Weight.bold]]), size: descr.pointSize)
attrs[.font] = bold
case .italic:
italic = italic ?? UIFont(descriptor: descr.withSymbolicTraits(.traitItalic) ?? descr, size: descr.pointSize)
attrs[.font] = italic
case .strikeThrough:
attrs[.strikethroughStyle] = NSUnderlineStyle.single.rawValue
case .snippet:
snippet = snippet ?? UIFont.monospacedSystemFont(ofSize: descr.pointSize, weight: .regular)
attrs[.font] = snippet
case .secret:
if let showSecrets {
if !showSecrets.contains(secretIdx) {
attrs[.foregroundColor] = UIColor.clear
attrs[.backgroundColor] = secretColor
}
attrs[secretAttrKey] = secretIdx
secretIdx += 1
handleTaps = true
} else {
attrs[.foregroundColor] = UIColor.clear
attrs[.backgroundColor] = secretColor
}
hasSecrets = true
case let .colored(color):
if let c = color.uiColor {
attrs[.foregroundColor] = UIColor(c)
}
case .uri:
attrs = linkAttrs()
if !preview {
let s = t.lowercased()
let link = s.hasPrefix("http://") || s.hasPrefix("https://")
? t
: "https://" + t
attrs[linkAttrKey] = NSURL(string: link)
attrs[webLinkAttrKey] = true
handleTaps = true
}
case let .simplexLink(linkType, simplexUri, smpHosts):
attrs = linkAttrs()
if !preview {
attrs[linkAttrKey] = NSURL(string: simplexUri)
handleTaps = true
}
if case .description = privacySimplexLinkModeDefault.get() {
t = simplexLinkText(linkType, smpHosts)
}
case let .mention(memberName):
if let m = mentions?[memberName] {
mention = mention ?? UIFont(descriptor: descr.addingAttributes([.traits: [UIFontDescriptor.TraitKey.weight: UIFont.Weight.semibold]]), size: descr.pointSize)
attrs[.font] = mention
if let ref = m.memberRef {
let name: String = if let alias = ref.localAlias, alias != "" {
"\(alias) (\(ref.displayName))"
} else {
ref.displayName
}
if m.memberId == userMemberId {
attrs[.foregroundColor] = UIColor.tintColor
}
t = mentionText(name)
} else {
t = mentionText(memberName)
}
}
case .email:
attrs = linkAttrs()
if !preview {
attrs[linkAttrKey] = NSURL(string: "mailto:" + ft.text)
handleTaps = true
}
case .phone:
attrs = linkAttrs()
if !preview {
attrs[linkAttrKey] = NSURL(string: "tel:" + t.replacingOccurrences(of: " ", with: ""))
handleTaps = true
}
case .none: ()
}
res.append(NSAttributedString(string: t, attributes: attrs))
}
} else {
res.append(NSMutableAttributedString(string: text, attributes: plain))
}
return (string: res, hasSecrets: hasSecrets, handleTaps: handleTaps)
func linkAttrs() -> [NSAttributedString.Key: Any] {
link = link ?? [
.font: font,
.foregroundColor: uiLinkColor,
.underlineStyle: NSUnderlineStyle.single.rawValue
]
return link!
}
}
@inline(__always)
private func mentionText(_ name: String) -> String {
name.contains(" @") ? "@'\(name)'" : "@\(name)"
}
func simplexLinkText(_ linkType: SimplexLinkType, _ smpHosts: [String]) -> String {
@@ -193,9 +371,9 @@ struct MsgContentView_Previews: PreviewProvider {
chat: Chat.sampleData,
text: chatItem.text,
formattedText: chatItem.formattedText,
textStyle: .body,
sender: chatItem.memberDisplayName,
meta: chatItem.meta,
showSecrets: false
meta: chatItem.meta
)
.environmentObject(Chat.sampleData)
}
@@ -41,7 +41,7 @@ struct ChatItemForwardingView: View {
.alert(item: $alert) { $0.alert }
}
@ViewBuilder private func forwardListView() -> some View {
private func forwardListView() -> some View {
VStack(alignment: .leading) {
if !chatsToForwardTo.isEmpty {
List {
@@ -131,9 +131,9 @@ struct ChatItemInfoView: View {
}
}
@ViewBuilder private func details() -> some View {
private func details() -> some View {
let meta = ci.meta
VStack(alignment: .leading, spacing: 16) {
return VStack(alignment: .leading, spacing: 16) {
Text(title)
.font(.largeTitle)
.bold()
@@ -197,7 +197,7 @@ struct ChatItemInfoView: View {
}
}
@ViewBuilder private func historyTab() -> some View {
private func historyTab() -> some View {
GeometryReader { g in
let maxWidth = (g.size.width - 32) * 0.84
ScrollView {
@@ -227,12 +227,13 @@ struct ChatItemInfoView: View {
}
}
@ViewBuilder private func itemVersionView(_ itemVersion: ChatItemVersion, _ maxWidth: CGFloat, current: Bool) -> some View {
VStack(alignment: .leading, spacing: 4) {
textBubble(itemVersion.msgContent.text, itemVersion.formattedText, nil)
private func itemVersionView(_ itemVersion: ChatItemVersion, _ maxWidth: CGFloat, current: Bool) -> some View {
let backgroundColor = chatItemFrameColor(ci, theme)
return VStack(alignment: .leading, spacing: 4) {
textBubble(itemVersion.msgContent.text, itemVersion.formattedText, nil, backgroundColor: UIColor(backgroundColor))
.padding(.horizontal, 12)
.padding(.vertical, 6)
.background(chatItemFrameColor(ci, theme))
.background(backgroundColor)
.modifier(ChatItemClipped())
.contextMenu {
if itemVersion.msgContent.text != "" {
@@ -257,9 +258,9 @@ struct ChatItemInfoView: View {
.frame(maxWidth: maxWidth, alignment: .leading)
}
@ViewBuilder private func textBubble(_ text: String, _ formattedText: [FormattedText]?, _ sender: String? = nil) -> some View {
@ViewBuilder private func textBubble(_ text: String, _ formattedText: [FormattedText]?, _ sender: String? = nil, backgroundColor: UIColor) -> some View {
if text != "" {
TextBubble(text: text, formattedText: formattedText, sender: sender, mentions: ci.mentions, userMemberId: userMemberId)
TextBubble(text: text, formattedText: formattedText, sender: sender, mentions: ci.mentions, userMemberId: userMemberId, backgroundColor: backgroundColor)
} else {
Text("no text")
.italic()
@@ -274,14 +275,16 @@ struct ChatItemInfoView: View {
var sender: String? = nil
var mentions: [String: CIMention]?
var userMemberId: String?
@State private var showSecrets = false
var backgroundColor: UIColor
@State private var showSecrets: Set<Int> = []
var body: some View {
toggleSecrets(formattedText, $showSecrets, messageText(text, formattedText, sender, mentions: mentions, userMemberId: userMemberId, showSecrets: showSecrets, secondaryColor: theme.colors.secondary))
let r = messageText(text, formattedText, sender: sender, mentions: mentions, userMemberId: userMemberId, showSecrets: showSecrets, backgroundColor: backgroundColor)
return msgTextResultView(r, Text(AttributedString(r.string)), showSecrets: $showSecrets)
}
}
@ViewBuilder private func quoteTab(_ qi: CIQuote) -> some View {
private func quoteTab(_ qi: CIQuote) -> some View {
GeometryReader { g in
let maxWidth = (g.size.width - 32) * 0.84
ScrollView {
@@ -299,9 +302,10 @@ struct ChatItemInfoView: View {
}
}
@ViewBuilder private func quotedMsgView(_ qi: CIQuote, _ maxWidth: CGFloat) -> some View {
VStack(alignment: .leading, spacing: 4) {
textBubble(qi.text, qi.formattedText, qi.getSender(nil))
private func quotedMsgView(_ qi: CIQuote, _ maxWidth: CGFloat) -> some View {
let backgroundColor = quotedMsgFrameColor(qi, theme)
return VStack(alignment: .leading, spacing: 4) {
textBubble(qi.text, qi.formattedText, qi.getSender(nil), backgroundColor: UIColor(backgroundColor))
.padding(.horizontal, 12)
.padding(.vertical, 6)
.background(quotedMsgFrameColor(qi, theme))
@@ -334,7 +338,7 @@ struct ChatItemInfoView: View {
: theme.appColors.receivedMessage
}
@ViewBuilder private func forwardedFromTab(_ forwardedFromItem: AChatItem) -> some View {
private func forwardedFromTab(_ forwardedFromItem: AChatItem) -> some View {
ScrollView {
VStack(alignment: .leading, spacing: 16) {
details()
@@ -372,7 +376,7 @@ struct ChatItemInfoView: View {
}
}
@ViewBuilder private func forwardedFromSender(_ forwardedFromItem: AChatItem) -> some View {
private func forwardedFromSender(_ forwardedFromItem: AChatItem) -> some View {
HStack {
ChatInfoImage(chat: Chat(chatInfo: forwardedFromItem.chatInfo), size: 48)
.padding(.trailing, 6)
@@ -403,7 +407,7 @@ struct ChatItemInfoView: View {
}
}
@ViewBuilder private func deliveryTab(_ memberDeliveryStatuses: [MemberDeliveryStatus]) -> some View {
private func deliveryTab(_ memberDeliveryStatuses: [MemberDeliveryStatus]) -> some View {
ScrollView {
VStack(alignment: .leading, spacing: 16) {
details()
@@ -418,7 +422,7 @@ struct ChatItemInfoView: View {
.frame(maxHeight: .infinity, alignment: .top)
}
@ViewBuilder private func memberDeliveryStatusesView(_ memberDeliveryStatuses: [MemberDeliveryStatus]) -> some View {
private func memberDeliveryStatusesView(_ memberDeliveryStatuses: [MemberDeliveryStatus]) -> some View {
LazyVStack(alignment: .leading, spacing: 12) {
let mss = membersStatuses(memberDeliveryStatuses)
if !mss.isEmpty {
@@ -18,6 +18,10 @@ extension EnvironmentValues {
static let defaultValue: Bool = true
}
struct ContainerBackground: EnvironmentKey {
static let defaultValue: UIColor = .clear
}
var showTimestamp: Bool {
get { self[ShowTimestamp.self] }
set { self[ShowTimestamp.self] = newValue }
@@ -27,6 +31,11 @@ extension EnvironmentValues {
get { self[Revealed.self] }
set { self[Revealed.self] = newValue }
}
var containerBackground: UIColor {
get { self[ContainerBackground.self] }
set { self[ContainerBackground.self] = newValue }
}
}
struct ChatItemView: View {
+15 -19
View File
@@ -71,10 +71,9 @@ struct ChatView: View {
}
}
@ViewBuilder
private var viewBody: some View {
let cInfo = chat.chatInfo
ZStack {
return ZStack {
let wallpaperImage = theme.wallpaper.type.image
let wallpaperType = theme.wallpaper.type
let backgroundColor = theme.wallpaper.background ?? wallpaperType.defaultBackgroundColor(theme.base, theme.colors.background)
@@ -1277,10 +1276,10 @@ struct ChatView: View {
if let selected = selectedChatItems, chatItem.canBeDeletedForSelf {
Color.clear
.contentShape(Rectangle())
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
let checked = selected.contains(chatItem.id)
selectUnselectChatItem(select: !checked, chatItem)
}
})
}
}
if let date = itemSeparation.date {
@@ -1469,7 +1468,7 @@ struct ChatView: View {
}
HStack(alignment: .top, spacing: 10) {
MemberProfileImage(member, size: memberImageSize, backgroundColor: theme.colors.background)
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
if let mem = m.getGroupMember(member.groupMemberId) {
selectedMember = mem
} else {
@@ -1478,7 +1477,7 @@ struct ChatView: View {
m.groupMembersIndexes[member.groupMemberId] = m.groupMembers.count - 1
selectedMember = mem
}
}
})
chatItemWithMenu(ci, range, maxWidth, itemSeparation)
.onPreferenceChange(DetermineWidth.Key.self) { msgWidth = $0 }
}
@@ -1528,9 +1527,9 @@ struct ChatView: View {
}
}
@ViewBuilder func chatItemWithMenu(_ ci: ChatItem, _ range: ClosedRange<Int>?, _ maxWidth: CGFloat, _ itemSeparation: ItemSeparation) -> some View {
func chatItemWithMenu(_ ci: ChatItem, _ range: ClosedRange<Int>?, _ maxWidth: CGFloat, _ itemSeparation: ItemSeparation) -> some View {
let alignment: Alignment = ci.chatDir.sent ? .trailing : .leading
VStack(alignment: alignment.horizontal, spacing: 3) {
return VStack(alignment: alignment.horizontal, spacing: 3) {
HStack {
if ci.chatDir.sent {
goToItemButton(true)
@@ -1622,9 +1621,9 @@ struct ChatView: View {
.padding(.horizontal, 6)
.padding(.vertical, 4)
.if(chat.chatInfo.featureEnabled(.reactions) && (ci.allowAddReaction || r.userReacted)) { v in
v.onTapGesture {
v.simultaneousGesture(TapGesture().onEnded {
setReaction(ci, add: !r.userReacted, reaction: r.reaction)
}
})
}
switch chat.chatInfo {
case let .group(groupInfo):
@@ -2214,15 +2213,12 @@ struct ChatView: View {
}
func goToItemInnerButton(_ alignStart: Bool, _ image: String, touchInProgress: Bool, _ onClick: @escaping () -> Void) -> some View {
Button {
onClick()
} label: {
Image(systemName: image)
.resizable()
.frame(width: 13, height: 13)
.padding([alignStart ? .trailing : .leading], 10)
.tint(theme.colors.secondary.opacity(touchInProgress ? 1.0 : 0.4))
}
Image(systemName: image)
.resizable()
.frame(width: 13, height: 13)
.padding([alignStart ? .trailing : .leading], 10)
.tint(theme.colors.secondary.opacity(touchInProgress ? 1.0 : 0.4))
.simultaneousGesture(TapGesture().onEnded(onClick))
}
@ViewBuilder
@@ -18,7 +18,7 @@ struct ComposeLinkView: View {
var body: some View {
HStack(alignment: .center, spacing: 8) {
if let linkPreview = linkPreview {
if let linkPreview {
linkPreviewView(linkPreview)
} else {
ProgressView()
@@ -1254,11 +1254,14 @@ struct ComposeView: View {
if pendingLinkUrl == url {
composeState = composeState.copy(preview: .linkPreview(linkPreview: nil))
getLinkPreview(url: url) { linkPreview in
if let linkPreview = linkPreview,
pendingLinkUrl == url {
if let linkPreview, pendingLinkUrl == url {
composeState = composeState.copy(preview: .linkPreview(linkPreview: linkPreview))
pendingLinkUrl = nil
} else {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
composeState = composeState.copy(preview: .noPreview)
}
}
pendingLinkUrl = nil
}
}
}
@@ -70,8 +70,10 @@ struct ContextItemView: View {
.lineLimit(lines)
}
private func contextMsgPreview(_ contextItem: ChatItem) -> Text {
return attachment() + messageText(contextItem.text, contextItem.formattedText, nil, preview: true, mentions: contextItem.mentions, userMemberId: nil, showSecrets: false, secondaryColor: theme.colors.secondary)
private func contextMsgPreview(_ contextItem: ChatItem) -> some View {
let r = messageText(contextItem.text, contextItem.formattedText, sender: nil, preview: true, mentions: contextItem.mentions, userMemberId: nil, showSecrets: nil, backgroundColor: UIColor(background))
let t = attachment() + Text(AttributedString(r.string))
return t.if(r.hasSecrets, transform: hiddenSecretsView)
func attachment() -> Text {
let isFileLoaded = if let fileSource = getLoadedFileSource(contextItem.file) {
@@ -263,13 +263,12 @@ struct SendMessageView: View {
@State private var pressed: TimeInterval? = nil
var body: some View {
Button(action: {}) {
Image(systemName: "mic.fill")
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
.foregroundColor(theme.colors.primary)
}
Image(systemName: "mic.fill")
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
.foregroundColor(theme.colors.primary)
.opacity(holdingVMR ? 0.7 : 1)
.disabled(disabled)
.frame(width: 31, height: 31)
.padding([.bottom, .trailing], 4)
@@ -279,9 +278,7 @@ struct SendMessageView: View {
pressed = ProcessInfo.processInfo.systemUptime
startVoiceMessageRecording?()
} else {
let now = ProcessInfo.processInfo.systemUptime
if let pressed = pressed,
now - pressed >= 1 {
if let pressed, ProcessInfo.processInfo.systemUptime - pressed >= 1 {
finishVoiceMessageRecording?()
}
holdingVMR = false
@@ -145,9 +145,9 @@ struct AddGroupMembersViewCommon: View {
return dummy
}()
@ViewBuilder private func inviteMembersButton() -> some View {
private func inviteMembersButton() -> some View {
let label: LocalizedStringKey = groupInfo.businessChat == nil ? "Invite to group" : "Invite to chat"
Button {
return Button {
inviteMembers()
} label: {
HStack {
@@ -292,9 +292,9 @@ struct GroupChatInfoView: View {
.disabled(!groupInfo.ready || chat.chatItems.isEmpty)
}
@ViewBuilder private func addMembersActionButton(width: CGFloat) -> some View {
if chat.chatInfo.incognito {
ZStack {
private func addMembersActionButton(width: CGFloat) -> some View {
ZStack {
if chat.chatInfo.incognito {
InfoViewButton(image: "link.badge.plus", title: "invite", width: width) {
groupLinkNavLinkActive = true
}
@@ -306,10 +306,7 @@ struct GroupChatInfoView: View {
}
.frame(width: 1, height: 1)
.hidden()
}
.disabled(!groupInfo.ready)
} else {
ZStack {
} else {
InfoViewButton(image: "person.fill.badge.plus", title: "invite", width: width) {
addMembersNavLinkActive = true
}
@@ -322,8 +319,8 @@ struct GroupChatInfoView: View {
.frame(width: 1, height: 1)
.hidden()
}
.disabled(!groupInfo.ready)
}
.disabled(!groupInfo.ready)
}
private func muteButton(width: CGFloat, nextNtfMode: MsgFilter) -> some View {
@@ -569,9 +566,9 @@ struct GroupChatInfoView: View {
}
}
@ViewBuilder private func leaveGroupButton() -> some View {
private func leaveGroupButton() -> some View {
let label: LocalizedStringKey = groupInfo.businessChat == nil ? "Leave group" : "Leave chat"
Button(role: .destructive) {
return Button(role: .destructive) {
alert = .leaveGroupAlert
} label: {
Label(label, systemImage: "rectangle.portrait.and.arrow.right")
@@ -196,7 +196,9 @@ struct GroupMentionsView: View {
newName = composeState.mentionMemberName(member.wrapped.memberProfile.displayName)
}
mentions[newName] = CIMention(groupMember: member.wrapped)
var msgMention = "@" + (newName.contains(" ") ? "'\(newName)'" : newName)
var msgMention = newName.contains(" ") || newName.last?.isPunctuation == true
? "@'\(newName)'"
: "@\(newName)"
var newPos = r.location + msgMention.count
let newMsgLength = composeState.message.count + msgMention.count - r.length
print(newPos)
@@ -18,6 +18,7 @@ struct GroupWelcomeView: View {
@State private var editMode = true
@FocusState private var keyboardVisible: Bool
@State private var showSaveDialog = false
@State private var showSecrets: Set<Int> = []
let maxByteCount = 1200
@@ -58,7 +59,8 @@ struct GroupWelcomeView: View {
}
private func textPreview() -> some View {
messageText(welcomeText, parseSimpleXMarkdown(welcomeText), nil, mentions: nil, userMemberId: nil, showSecrets: false, secondaryColor: theme.colors.secondary)
let r = messageText(welcomeText, parseSimpleXMarkdown(welcomeText), sender: nil, mentions: nil, userMemberId: nil, showSecrets: showSecrets, backgroundColor: UIColor(theme.colors.background))
return msgTextResultView(r, Text(AttributedString(r.string)), showSecrets: $showSecrets)
.frame(minHeight: 130, alignment: .topLeading)
.frame(maxWidth: .infinity, alignment: .leading)
}
@@ -90,7 +90,7 @@ struct ChatListNavLink: View {
.actionSheet(item: $actionSheet) { $0.actionSheet }
}
@ViewBuilder private func contactNavLink(_ contact: Contact) -> some View {
private func contactNavLink(_ contact: Contact) -> some View {
Group {
if contact.activeConn == nil && contact.profile.contactLink != nil && contact.active {
ChatPreviewView(chat: chat, progressByTimeout: Binding.constant(false))
@@ -243,7 +243,7 @@ struct ChatListNavLink: View {
}
}
@ViewBuilder private func noteFolderNavLink(_ noteFolder: NoteFolder) -> some View {
private func noteFolderNavLink(_ noteFolder: NoteFolder) -> some View {
NavLinkPlain(
chatId: chat.chatInfo.id,
selection: $chatModel.chatId,
@@ -335,9 +335,9 @@ struct ChatListView: View {
}
}
@ViewBuilder private var chatList: some View {
private var chatList: some View {
let cs = filteredChats()
ZStack {
return ZStack {
ScrollViewReader { scrollProxy in
List {
if !chatModel.chats.isEmpty {
@@ -804,7 +804,7 @@ struct TagsView: View {
}
}
@ViewBuilder private func expandedPresetTagsFiltersView() -> some View {
private func expandedPresetTagsFiltersView() -> some View {
ForEach(PresetTag.allCases, id: \.id) { tag in
if (chatTagsModel.presetTags[tag] ?? 0) > 0 {
expandedTagFilterView(tag)
@@ -187,13 +187,14 @@ struct ChatPreviewView: View {
.kerning(-2)
}
private func chatPreviewLayout(_ text: Text?, draft: Bool = false, _ hasFilePreview: Bool = false) -> some View {
private func chatPreviewLayout(_ text: Text?, draft: Bool = false, hasFilePreview: Bool = false, hasSecrets: Bool) -> some View {
ZStack(alignment: .topTrailing) {
let s = chat.chatStats
let mentionWidth: CGFloat = if s.unreadMentions > 0 && s.unreadCount > 1 { dynamicSize(userFont).unreadCorner } else { 0 }
let t = text
.lineLimit(userFont <= .xxxLarge ? 2 : 1)
.multilineTextAlignment(.leading)
.if(hasSecrets, transform: hiddenSecretsView)
.frame(maxWidth: .infinity, alignment: .topLeading)
.padding(.leading, hasFilePreview ? 0 : 8)
.padding(.trailing, mentionWidth + (hasFilePreview ? 38 : 36))
@@ -259,11 +260,13 @@ struct ChatPreviewView: View {
}
}
private func messageDraft(_ draft: ComposeState) -> Text {
private func messageDraft(_ draft: ComposeState) -> (Text, Bool) {
let msg = draft.message
return image("rectangle.and.pencil.and.ellipsis", color: theme.colors.primary)
+ attachment()
+ messageText(msg, parseSimpleXMarkdown(msg), nil, preview: true, mentions: draft.mentions, userMemberId: nil, showSecrets: false, secondaryColor: theme.colors.secondary)
let r = messageText(msg, parseSimpleXMarkdown(msg), sender: nil, preview: true, mentions: draft.mentions, userMemberId: nil, showSecrets: nil, backgroundColor: UIColor(theme.colors.background))
return (image("rectangle.and.pencil.and.ellipsis", color: theme.colors.primary)
+ attachment()
+ Text(AttributedString(r.string)),
r.hasSecrets)
func image(_ s: String, color: Color = Color(uiColor: .tertiaryLabel)) -> Text {
Text(Image(systemName: s)).foregroundColor(color) + textSpace
@@ -279,10 +282,11 @@ struct ChatPreviewView: View {
}
}
func chatItemPreview(_ cItem: ChatItem) -> Text {
func chatItemPreview(_ cItem: ChatItem) -> (Text, Bool) {
let itemText = cItem.meta.itemDeleted == nil ? cItem.text : markedDeletedText()
let itemFormattedText = cItem.meta.itemDeleted == nil ? cItem.formattedText : nil
return messageText(itemText, itemFormattedText, cItem.memberDisplayName, icon: nil, preview: true, mentions: cItem.mentions, userMemberId: chat.chatInfo.groupInfo?.membership.memberId, showSecrets: false, secondaryColor: theme.colors.secondary, prefix: prefix())
let r = messageText(itemText, itemFormattedText, sender: cItem.memberDisplayName, preview: true, mentions: cItem.mentions, userMemberId: chat.chatInfo.groupInfo?.membership.memberId, showSecrets: nil, backgroundColor: UIColor(theme.colors.background), prefix: prefix())
return (Text(AttributedString(r.string)), r.hasSecrets)
// same texts are in markedDeletedText in MarkedDeletedItemView, but it returns LocalizedStringKey;
// can be refactored into a single function if functions calling these are changed to return same type
@@ -309,19 +313,21 @@ struct ChatPreviewView: View {
}
}
func prefix() -> Text {
func prefix() -> NSAttributedString? {
switch cItem.content.msgContent {
case let .report(_, reason): return Text(!itemText.isEmpty ? "\(reason.text): " : reason.text).italic().foregroundColor(Color.red)
default: return Text("")
case let .report(_, reason): reason.attrString
default: nil
}
}
}
@ViewBuilder private func chatMessagePreview(_ cItem: ChatItem?, _ hasFilePreview: Bool = false) -> some View {
if chatModel.draftChatId == chat.id, let draft = chatModel.draft {
chatPreviewLayout(messageDraft(draft), draft: true, hasFilePreview)
let (t, hasSecrets) = messageDraft(draft)
chatPreviewLayout(t, draft: true, hasFilePreview: hasFilePreview, hasSecrets: hasSecrets)
} else if let cItem = cItem {
chatPreviewLayout(itemStatusMark(cItem) + chatItemPreview(cItem), hasFilePreview)
let (t, hasSecrets) = chatItemPreview(cItem)
chatPreviewLayout(itemStatusMark(cItem) + t, hasFilePreview: hasFilePreview, hasSecrets: hasSecrets)
} else {
switch (chat.chatInfo) {
case let .direct(contact):
@@ -348,7 +354,6 @@ struct ChatPreviewView: View {
}
@ViewBuilder func chatItemContentPreview(_ chat: Chat, _ ci: ChatItem) -> some View {
let linkClicksEnabled = privacyChatListOpenLinksDefault.get() != PrivacyChatListOpenLinksMode.no
let mc = ci.content.msgContent
switch mc {
case let .link(_, preview):
@@ -370,17 +375,7 @@ struct ChatPreviewView: View {
.cornerRadius(8)
}
.onTapGesture {
switch privacyChatListOpenLinksDefault.get() {
case .yes: UIApplication.shared.open(preview.uri)
case .no: ItemsModel.shared.loadOpenChat(chat.id)
case .ask: AlertManager.shared.showAlert(
Alert(title: Text("Open web link?"),
message: Text(preview.uri.absoluteString),
primaryButton: .default(Text("Open chat"), action: { ItemsModel.shared.loadOpenChat(chat.id) }),
secondaryButton: .default(Text("Open link"), action: { UIApplication.shared.open(preview.uri) })
)
)
}
openBrowserAlert(uri: preview.uri)
}
}
case let .image(_, image):
@@ -410,7 +405,7 @@ struct ChatPreviewView: View {
: chatPreviewInfoText("you are invited to group")
}
@ViewBuilder private func chatPreviewInfoText(_ text: LocalizedStringKey) -> some View {
private func chatPreviewInfoText(_ text: LocalizedStringKey) -> some View {
Text(text)
.frame(maxWidth: .infinity, minHeight: 44, maxHeight: 44, alignment: .topLeading)
.padding([.leading, .trailing], 8)
@@ -490,7 +485,7 @@ struct ChatPreviewView: View {
}
}
@ViewBuilder func groupReportsIcon(size: CGFloat) -> some View {
func groupReportsIcon(size: CGFloat) -> some View {
Image(systemName: "flag")
.resizable()
.scaledToFit()
@@ -245,7 +245,7 @@ struct ServersSummaryView: View {
}
}
@ViewBuilder private func smpServersListView(
private func smpServersListView(
_ servers: [SMPServerSummary],
_ statsStartedAt: Date,
_ header: LocalizedStringKey? = nil,
@@ -256,7 +256,7 @@ struct ServersSummaryView: View {
? serverAddress($0.smpServer) < serverAddress($1.smpServer)
: $0.hasSubs && !$1.hasSubs
}
Section {
return Section {
ForEach(sortedServers) { server in
smpServerView(server, statsStartedAt)
}
@@ -318,14 +318,14 @@ struct ServersSummaryView: View {
return onionHosts == .require ? .indigo : .accentColor
}
@ViewBuilder private func xftpServersListView(
private func xftpServersListView(
_ servers: [XFTPServerSummary],
_ statsStartedAt: Date,
_ header: LocalizedStringKey? = nil,
_ footer: LocalizedStringKey? = nil
) -> some View {
let sortedServers = servers.sorted { serverAddress($0.xftpServer) < serverAddress($1.xftpServer) }
Section {
return Section {
ForEach(sortedServers) { server in
xftpServerView(server, statsStartedAt)
}
@@ -138,7 +138,7 @@ struct TagListView: View {
}
}
@ViewBuilder private func radioButton(selected: Bool) -> some View {
private func radioButton(selected: Bool) -> some View {
Image(systemName: selected ? "checkmark.circle.fill" : "circle")
.imageScale(.large)
.foregroundStyle(selected ? Color.accentColor : Color(.tertiaryLabel))
@@ -140,9 +140,9 @@ struct ContactListNavLink: View {
}
}
@ViewBuilder private func previewTitle(_ contact: Contact, titleColor: Color) -> some View {
private func previewTitle(_ contact: Contact, titleColor: Color) -> some View {
let t = Text(chat.chatInfo.chatViewName).foregroundColor(titleColor)
(
return (
contact.verified == true
? verifiedIcon + t
: t
@@ -28,7 +28,7 @@ struct DatabaseErrorView: View {
}
}
@ViewBuilder private func databaseErrorView() -> some View {
private func databaseErrorView() -> some View {
VStack(alignment: .center, spacing: 20) {
switch status {
case let .errorNotADatabase(dbFile):
@@ -9,6 +9,7 @@
import SwiftUI
extension View {
@inline(__always)
@ViewBuilder func `if`<Content: View>(_ condition: Bool, transform: (Self) -> Content) -> some View {
if condition {
transform(self)
@@ -36,9 +37,9 @@ struct PrivacyBlur: ViewModifier {
.overlay {
if (blurred && enabled) {
Color.clear.contentShape(Rectangle())
.onTapGesture {
.simultaneousGesture(TapGesture().onEnded {
blurred = false
}
})
}
}
.onReceive(NotificationCenter.default.publisher(for: .chatViewWillBeginScrolling)) { _ in
@@ -28,7 +28,7 @@ struct PasscodeEntry: View {
}
}
@ViewBuilder private func passwordView() -> some View {
private func passwordView() -> some View {
Text(
password == ""
? " "
@@ -85,7 +85,7 @@ struct NewChatSheet: View {
}
}
@ViewBuilder private func viewBody(_ showArchive: Bool) -> some View {
private func viewBody(_ showArchive: Bool) -> some View {
List {
HStack {
ContactsListSearchBar(
@@ -258,7 +258,7 @@ struct ContactsList: View {
}
}
@ViewBuilder private func noResultSection(text: String) -> some View {
private func noResultSection(text: String) -> some View {
Section {
Text(text)
.foregroundColor(theme.colors.secondary)
@@ -506,7 +506,7 @@ private struct ActiveProfilePicker: View {
}
}
@ViewBuilder private func profilerPickerUserOption(_ user: User) -> some View {
private func profilerPickerUserOption(_ user: User) -> some View {
Button {
if selectedProfile == user && incognitoEnabled {
incognitoEnabled = false
@@ -304,11 +304,11 @@ struct ChooseServerOperators: View {
}
}
@ViewBuilder private func operatorCheckView(_ serverOperator: ServerOperator) -> some View {
private func operatorCheckView(_ serverOperator: ServerOperator) -> some View {
let checked = selectedOperatorIds.contains(serverOperator.operatorId)
let icon = checked ? "checkmark.circle.fill" : "circle"
let iconColor = checked ? theme.colors.primary : Color(uiColor: .tertiaryLabel).asAnotherColorFromSecondary(theme)
HStack(spacing: 10) {
return HStack(spacing: 10) {
Image(serverOperator.largeLogo(colorScheme))
.resizable()
.scaledToFit()
@@ -38,7 +38,6 @@ extension AppSettings {
privacyLinkPreviewsGroupDefault.set(val)
def.setValue(val, forKey: DEFAULT_PRIVACY_LINK_PREVIEWS)
}
if let val = privacyChatListOpenLinks { privacyChatListOpenLinksDefault.set(val) }
if let val = privacyShowChatPreviews { def.setValue(val, forKey: DEFAULT_PRIVACY_SHOW_CHAT_PREVIEWS) }
if let val = privacySaveLastDraft { def.setValue(val, forKey: DEFAULT_PRIVACY_SAVE_LAST_DRAFT) }
if let val = privacyProtectScreen { def.setValue(val, forKey: DEFAULT_PRIVACY_PROTECT_SCREEN) }
@@ -78,7 +77,6 @@ extension AppSettings {
c.privacyAskToApproveRelays = privacyAskToApproveRelaysGroupDefault.get()
c.privacyAcceptImages = privacyAcceptImagesGroupDefault.get()
c.privacyLinkPreviews = def.bool(forKey: DEFAULT_PRIVACY_LINK_PREVIEWS)
c.privacyChatListOpenLinks = privacyChatListOpenLinksDefault.get()
c.privacyShowChatPreviews = def.bool(forKey: DEFAULT_PRIVACY_SHOW_CHAT_PREVIEWS)
c.privacySaveLastDraft = def.bool(forKey: DEFAULT_PRIVACY_SAVE_LAST_DRAFT)
c.privacyProtectScreen = def.bool(forKey: DEFAULT_PRIVACY_PROTECT_SCREEN)
@@ -38,9 +38,9 @@ struct OperatorView: View {
.allowsHitTesting(!testing)
}
@ViewBuilder private func operatorView() -> some View {
private func operatorView() -> some View {
let duplicateHosts = findDuplicateHosts(serverErrors)
VStack {
return VStack {
List {
Section {
infoViewLink()
@@ -500,14 +500,14 @@ struct SingleOperatorUsageConditionsView: View {
}
}
@ViewBuilder private func acceptConditionsButton() -> some View {
private func acceptConditionsButton() -> some View {
let operatorIds = ChatModel.shared.conditions.serverOperators
.filter {
$0.operatorId == userServers[operatorIndex].operator_.operatorId || // Opened operator
($0.enabled && !$0.conditionsAcceptance.conditionsAccepted) // Other enabled operators with conditions not accepted
}
.map { $0.operatorId }
Button {
return Button {
acceptForOperators(operatorIds, operatorIndex)
} label: {
Text("Accept conditions")
@@ -38,9 +38,9 @@ struct YourServersView: View {
.allowsHitTesting(!testing)
}
@ViewBuilder private func yourServersView() -> some View {
private func yourServersView() -> some View {
let duplicateHosts = findDuplicateHosts(serverErrors)
List {
return List {
if !userServers[operatorIndex].smpServers.filter({ !$0.deleted }).isEmpty {
Section {
ForEach($userServers[operatorIndex].smpServers) { srv in
@@ -14,7 +14,6 @@ struct PrivacySettings: View {
@EnvironmentObject var theme: AppTheme
@AppStorage(DEFAULT_PRIVACY_ACCEPT_IMAGES) private var autoAcceptImages = true
@AppStorage(DEFAULT_PRIVACY_LINK_PREVIEWS) private var useLinkPreviews = true
@State private var chatListOpenLinks = privacyChatListOpenLinksDefault.get()
@AppStorage(DEFAULT_PRIVACY_SHOW_CHAT_PREVIEWS) private var showChatPreviews = true
@AppStorage(DEFAULT_PRIVACY_SAVE_LAST_DRAFT) private var saveLastDraft = true
@AppStorage(GROUP_DEFAULT_PRIVACY_ENCRYPT_LOCAL_FILES, store: groupDefaults) private var encryptLocalFiles = true
@@ -77,17 +76,6 @@ struct PrivacySettings: View {
privacyLinkPreviewsGroupDefault.set(linkPreviews)
}
}
settingsRow("arrow.up.right.circle", color: theme.colors.secondary) {
Picker("Open links from chat list", selection: $chatListOpenLinks) {
ForEach(PrivacyChatListOpenLinksMode.allCases) { mode in
Text(mode.text)
}
}
}
.frame(height: 36)
.onChange(of: chatListOpenLinks) { mode in
privacyChatListOpenLinksDefault.set(mode)
}
settingsRow("message", color: theme.colors.secondary) {
Toggle("Show last messages", isOn: $showChatPreviews)
}
@@ -29,7 +29,6 @@ let DEFAULT_WEBRTC_ICE_SERVERS = "webrtcICEServers"
let DEFAULT_CALL_KIT_CALLS_IN_RECENTS = "callKitCallsInRecents"
let DEFAULT_PRIVACY_ACCEPT_IMAGES = "privacyAcceptImages" // unused. Use GROUP_DEFAULT_PRIVACY_ACCEPT_IMAGES instead
let DEFAULT_PRIVACY_LINK_PREVIEWS = "privacyLinkPreviews" // deprecated, moved to app group
let DEFAULT_PRIVACY_CHAT_LIST_OPEN_LINKS = "privacyChatListOpenLinks"
let DEFAULT_PRIVACY_SIMPLEX_LINK_MODE = "privacySimplexLinkMode"
let DEFAULT_PRIVACY_SHOW_CHAT_PREVIEWS = "privacyShowChatPreviews"
let DEFAULT_PRIVACY_SAVE_LAST_DRAFT = "privacySaveLastDraft"
@@ -185,8 +184,6 @@ let connectViaLinkTabDefault = EnumDefault<ConnectViaLinkTab>(defaults: UserDefa
let privacySimplexLinkModeDefault = EnumDefault<SimpleXLinkMode>(defaults: UserDefaults.standard, forKey: DEFAULT_PRIVACY_SIMPLEX_LINK_MODE, withDefault: .description)
let privacyChatListOpenLinksDefault = EnumDefault<PrivacyChatListOpenLinksMode>(defaults: UserDefaults.standard, forKey: DEFAULT_PRIVACY_CHAT_LIST_OPEN_LINKS, withDefault: PrivacyChatListOpenLinksMode.ask)
let privacyLocalAuthModeDefault = EnumDefault<LAMode>(defaults: UserDefaults.standard, forKey: DEFAULT_LA_MODE, withDefault: .system)
let privacyDeliveryReceiptsSet = BoolDefault(defaults: UserDefaults.standard, forKey: DEFAULT_PRIVACY_DELIVERY_RECEIPTS_SET)
@@ -283,159 +280,159 @@ struct SettingsView: View {
}
}
@ViewBuilder func settingsView() -> some View {
let user = chatModel.currentUser
List {
Section(header: Text("Settings").foregroundColor(theme.colors.secondary)) {
NavigationLink {
NotificationsView()
.navigationTitle("Notifications")
.modifier(ThemedBackground(grouped: true))
} label: {
HStack {
notificationsIcon()
Text("Notifications")
}
}
.disabled(chatModel.chatRunning != true)
NavigationLink {
NetworkAndServers()
.navigationTitle("Network & servers")
.modifier(ThemedBackground(grouped: true))
} label: {
settingsRow("externaldrive.connected.to.line.below", color: theme.colors.secondary) { Text("Network & servers") }
}
.disabled(chatModel.chatRunning != true)
NavigationLink {
CallSettings()
.navigationTitle("Your calls")
.modifier(ThemedBackground(grouped: true))
} label: {
settingsRow("video", color: theme.colors.secondary) { Text("Audio & video calls") }
}
.disabled(chatModel.chatRunning != true)
NavigationLink {
PrivacySettings()
.navigationTitle("Your privacy")
.modifier(ThemedBackground(grouped: true))
} label: {
settingsRow("lock", color: theme.colors.secondary) { Text("Privacy & security") }
}
.disabled(chatModel.chatRunning != true)
if UIApplication.shared.supportsAlternateIcons {
NavigationLink {
AppearanceSettings()
.navigationTitle("Appearance")
.modifier(ThemedBackground(grouped: true))
} label: {
settingsRow("sun.max", color: theme.colors.secondary) { Text("Appearance") }
}
.disabled(chatModel.chatRunning != true)
func settingsView() -> some View {
List {
let user = chatModel.currentUser
Section(header: Text("Settings").foregroundColor(theme.colors.secondary)) {
NavigationLink {
NotificationsView()
.navigationTitle("Notifications")
.modifier(ThemedBackground(grouped: true))
} label: {
HStack {
notificationsIcon()
Text("Notifications")
}
}
.disabled(chatModel.chatRunning != true)
Section(header: Text("Chat database").foregroundColor(theme.colors.secondary)) {
chatDatabaseRow()
NavigationLink {
MigrateFromDevice(showProgressOnSettings: $showProgress)
.toolbar {
// Redaction broken for `.navigationTitle` - using a toolbar item instead.
ToolbarItem(placement: .principal) {
Text("Migrate device").font(.headline)
}
}
.modifier(ThemedBackground(grouped: true))
.navigationBarTitleDisplayMode(.large)
} label: {
settingsRow("tray.and.arrow.up", color: theme.colors.secondary) { Text("Migrate to another device") }
}
NavigationLink {
NetworkAndServers()
.navigationTitle("Network & servers")
.modifier(ThemedBackground(grouped: true))
} label: {
settingsRow("externaldrive.connected.to.line.below", color: theme.colors.secondary) { Text("Network & servers") }
}
Section(header: Text("Help").foregroundColor(theme.colors.secondary)) {
if let user = user {
NavigationLink {
ChatHelp(dismissSettingsSheet: dismiss)
.navigationTitle("Welcome \(user.displayName)!")
.modifier(ThemedBackground())
.frame(maxHeight: .infinity, alignment: .top)
} label: {
settingsRow("questionmark", color: theme.colors.secondary) { Text("How to use it") }
}
}
.disabled(chatModel.chatRunning != true)
NavigationLink {
CallSettings()
.navigationTitle("Your calls")
.modifier(ThemedBackground(grouped: true))
} label: {
settingsRow("video", color: theme.colors.secondary) { Text("Audio & video calls") }
}
.disabled(chatModel.chatRunning != true)
NavigationLink {
PrivacySettings()
.navigationTitle("Your privacy")
.modifier(ThemedBackground(grouped: true))
} label: {
settingsRow("lock", color: theme.colors.secondary) { Text("Privacy & security") }
}
.disabled(chatModel.chatRunning != true)
if UIApplication.shared.supportsAlternateIcons {
NavigationLink {
WhatsNewView(viaSettings: true, updatedConditions: false)
.modifier(ThemedBackground())
.navigationBarTitleDisplayMode(.inline)
AppearanceSettings()
.navigationTitle("Appearance")
.modifier(ThemedBackground(grouped: true))
} label: {
settingsRow("plus", color: theme.colors.secondary) { Text("What's new") }
settingsRow("sun.max", color: theme.colors.secondary) { Text("Appearance") }
}
.disabled(chatModel.chatRunning != true)
}
}
Section(header: Text("Chat database").foregroundColor(theme.colors.secondary)) {
chatDatabaseRow()
NavigationLink {
MigrateFromDevice(showProgressOnSettings: $showProgress)
.toolbar {
// Redaction broken for `.navigationTitle` - using a toolbar item instead.
ToolbarItem(placement: .principal) {
Text("Migrate device").font(.headline)
}
}
.modifier(ThemedBackground(grouped: true))
.navigationBarTitleDisplayMode(.large)
} label: {
settingsRow("tray.and.arrow.up", color: theme.colors.secondary) { Text("Migrate to another device") }
}
}
Section(header: Text("Help").foregroundColor(theme.colors.secondary)) {
if let user = user {
NavigationLink {
SimpleXInfo(onboarding: false)
.navigationBarTitle("", displayMode: .inline)
ChatHelp(dismissSettingsSheet: dismiss)
.navigationTitle("Welcome \(user.displayName)!")
.modifier(ThemedBackground())
.frame(maxHeight: .infinity, alignment: .top)
} label: {
settingsRow("info", color: theme.colors.secondary) { Text("About SimpleX Chat") }
settingsRow("questionmark", color: theme.colors.secondary) { Text("How to use it") }
}
settingsRow("number", color: theme.colors.secondary) {
Button("Send questions and ideas") {
dismiss()
DispatchQueue.main.async {
UIApplication.shared.open(simplexTeamURL)
}
}
NavigationLink {
WhatsNewView(viaSettings: true, updatedConditions: false)
.modifier(ThemedBackground())
.navigationBarTitleDisplayMode(.inline)
} label: {
settingsRow("plus", color: theme.colors.secondary) { Text("What's new") }
}
NavigationLink {
SimpleXInfo(onboarding: false)
.navigationBarTitle("", displayMode: .inline)
.modifier(ThemedBackground())
.frame(maxHeight: .infinity, alignment: .top)
} label: {
settingsRow("info", color: theme.colors.secondary) { Text("About SimpleX Chat") }
}
settingsRow("number", color: theme.colors.secondary) {
Button("Send questions and ideas") {
dismiss()
DispatchQueue.main.async {
UIApplication.shared.open(simplexTeamURL)
}
}
.disabled(chatModel.chatRunning != true)
settingsRow("envelope", color: theme.colors.secondary) { Text("[Send us email](mailto:chat@simplex.chat)") }
}
.disabled(chatModel.chatRunning != true)
settingsRow("envelope", color: theme.colors.secondary) { Text("[Send us email](mailto:chat@simplex.chat)") }
}
Section(header: Text("Support SimpleX Chat").foregroundColor(theme.colors.secondary)) {
settingsRow("keyboard", color: theme.colors.secondary) { Text("[Contribute](https://github.com/simplex-chat/simplex-chat#contribute)") }
settingsRow("star", color: theme.colors.secondary) {
Button("Rate the app") {
if let scene = sceneDelegate.windowScene {
SKStoreReviewController.requestReview(in: scene)
}
Section(header: Text("Support SimpleX Chat").foregroundColor(theme.colors.secondary)) {
settingsRow("keyboard", color: theme.colors.secondary) { Text("[Contribute](https://github.com/simplex-chat/simplex-chat#contribute)") }
settingsRow("star", color: theme.colors.secondary) {
Button("Rate the app") {
if let scene = sceneDelegate.windowScene {
SKStoreReviewController.requestReview(in: scene)
}
}
ZStack(alignment: .leading) {
Image(colorScheme == .dark ? "github_light" : "github")
.resizable()
.frame(width: 24, height: 24)
.opacity(0.5)
.colorMultiply(theme.colors.secondary)
Text("[Star on GitHub](https://github.com/simplex-chat/simplex-chat)")
.padding(.leading, indent)
}
}
ZStack(alignment: .leading) {
Image(colorScheme == .dark ? "github_light" : "github")
.resizable()
.frame(width: 24, height: 24)
.opacity(0.5)
.colorMultiply(theme.colors.secondary)
Text("[Star on GitHub](https://github.com/simplex-chat/simplex-chat)")
.padding(.leading, indent)
}
}
Section(header: Text("Develop").foregroundColor(theme.colors.secondary)) {
NavigationLink {
DeveloperView()
.navigationTitle("Developer tools")
.modifier(ThemedBackground(grouped: true))
} label: {
settingsRow("chevron.left.forwardslash.chevron.right", color: theme.colors.secondary) { Text("Developer tools") }
}
NavigationLink {
VersionView()
.navigationBarTitle("App version")
.modifier(ThemedBackground())
} label: {
Text("v\(appVersion ?? "?") (\(appBuild ?? "?"))")
}
Section(header: Text("Develop").foregroundColor(theme.colors.secondary)) {
NavigationLink {
DeveloperView()
.navigationTitle("Developer tools")
.modifier(ThemedBackground(grouped: true))
} label: {
settingsRow("chevron.left.forwardslash.chevron.right", color: theme.colors.secondary) { Text("Developer tools") }
}
NavigationLink {
VersionView()
.navigationBarTitle("App version")
.modifier(ThemedBackground())
} label: {
Text("v\(appVersion ?? "?") (\(appBuild ?? "?"))")
}
}
.navigationTitle("Your settings")
.modifier(ThemedBackground(grouped: true))
.onDisappear {
chatModel.showingTerminal = false
chatModel.terminalItems = []
}
}
.navigationTitle("Your settings")
.modifier(ThemedBackground(grouped: true))
.onDisappear {
chatModel.showingTerminal = false
chatModel.terminalItems = []
}
}
private func chatDatabaseRow() -> some View {
@@ -133,7 +133,6 @@ struct UserProfile: View {
.alert(item: $alert) { a in userProfileAlert(a, $profile.displayName) }
}
@ViewBuilder
private func overlayButton(
_ systemName: String,
edge: Edge.Set,
@@ -221,11 +221,11 @@ struct UserProfilesView: View {
!user.hidden ? nil : trimmedSearchTextOrPassword
}
@ViewBuilder private func profileActionView(_ action: UserProfileAction) -> some View {
private func profileActionView(_ action: UserProfileAction) -> some View {
let passwordValid = actionPassword == actionPassword.trimmingCharacters(in: .whitespaces)
let passwordField = PassphraseField(key: $actionPassword, placeholder: "Profile password", valid: passwordValid)
let actionEnabled: (User) -> Bool = { user in actionPassword != "" && passwordValid && correctPassword(user, actionPassword) }
List {
return List {
switch action {
case let .deleteUser(user, delSMPQueues):
actionHeader("Delete profile", user)
@@ -814,8 +814,9 @@
<target state="translated">جهة الاتصال مخفية:</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Contact is connected" xml:space="preserve">
<trans-unit id="Contact is connected" xml:space="preserve" approved="no">
<source>Contact is connected</source>
<target state="translated">تم الاتصال</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Contact is not connected yet!" xml:space="preserve">
@@ -850,8 +851,9 @@
<source>Core built at: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Core version: v%@" xml:space="preserve">
<trans-unit id="Core version: v%@" xml:space="preserve" approved="no">
<source>Core version: v%@</source>
<target state="translated">الإصدار الأساسي: v%@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create" xml:space="preserve" approved="no">
@@ -901,8 +903,9 @@
<target state="translated">عبارة المرور الحالية…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Currently maximum supported file size is %@." xml:space="preserve">
<trans-unit id="Currently maximum supported file size is %@." xml:space="preserve" approved="no">
<source>Currently maximum supported file size is %@.</source>
<target state="translated">الحد الأقصى لحجم الملف المدعوم حاليًا هو %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Dark" xml:space="preserve" approved="no">
@@ -920,9 +923,11 @@
<target state="translated">قاعدة البيانات مُعمّاة!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Database encryption passphrase will be updated and stored in the keychain.&#10;" xml:space="preserve">
<trans-unit id="Database encryption passphrase will be updated and stored in the keychain.&#10;" xml:space="preserve" approved="no">
<source>Database encryption passphrase will be updated and stored in the keychain.
</source>
<target state="translated">سيتم تحديث عبارة المرور الخاصة بتشفير قاعدة البيانات وتخزينها في سلسلة المفاتيح.
</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Database encryption passphrase will be updated.&#10;" xml:space="preserve" approved="no">
@@ -957,8 +962,9 @@
<target state="translated">عبارة مرور قاعدة البيانات وتصديرها</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Database passphrase is different from saved in the keychain." xml:space="preserve">
<trans-unit id="Database passphrase is different from saved in the keychain." xml:space="preserve" approved="no">
<source>Database passphrase is different from saved in the keychain.</source>
<target state="translated">عبارة المرور الخاصة بقاعدة البيانات مختلفة عن تلك المحفوظة في سلسلة المفاتيح.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Database passphrase is required to open chat." xml:space="preserve" approved="no">
@@ -966,9 +972,11 @@
<target state="translated">عبارة مرور قاعدة البيانات مطلوبة لفتح الدردشة.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Database will be encrypted and the passphrase stored in the keychain.&#10;" xml:space="preserve">
<trans-unit id="Database will be encrypted and the passphrase stored in the keychain.&#10;" xml:space="preserve" approved="no">
<source>Database will be encrypted and the passphrase stored in the keychain.
</source>
<target state="translated">سيتم تشفير قاعدة البيانات وتخزين عبارة المرور في سلسلة المفاتيح.
</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Database will be encrypted.&#10;" xml:space="preserve" approved="no">
@@ -978,8 +986,9 @@
</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Database will be migrated when the app restarts" xml:space="preserve">
<trans-unit id="Database will be migrated when the app restarts" xml:space="preserve" approved="no">
<source>Database will be migrated when the app restarts</source>
<target state="translated">سيتم نقل قاعدة البيانات عند إعادة تشغيل التطبيق</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Decentralized" xml:space="preserve" approved="no">
@@ -1079,36 +1088,44 @@
<target state="translated">حذف المجموعة؟</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete invitation" xml:space="preserve">
<trans-unit id="Delete invitation" xml:space="preserve" approved="no">
<source>Delete invitation</source>
<target state="translated">حذف الدعوة</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete link" xml:space="preserve">
<trans-unit id="Delete link" xml:space="preserve" approved="no">
<source>Delete link</source>
<target state="translated">حذف الرابط</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete link?" xml:space="preserve">
<trans-unit id="Delete link?" xml:space="preserve" approved="no">
<source>Delete link?</source>
<target state="translated">حذف الرابط؟</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete message?" xml:space="preserve">
<trans-unit id="Delete message?" xml:space="preserve" approved="no">
<source>Delete message?</source>
<target state="translated">حذف الرسالة؟</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete messages" xml:space="preserve">
<trans-unit id="Delete messages" xml:space="preserve" approved="no">
<source>Delete messages</source>
<target state="translated">حذف الرسائل</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete messages after" xml:space="preserve">
<trans-unit id="Delete messages after" xml:space="preserve" approved="no">
<source>Delete messages after</source>
<target state="translated">حذف الرسائل بعد</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete old database" xml:space="preserve">
<trans-unit id="Delete old database" xml:space="preserve" approved="no">
<source>Delete old database</source>
<target state="translated">حذف قاعدة البيانات القديمة</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete old database?" xml:space="preserve">
<trans-unit id="Delete old database?" xml:space="preserve" approved="no">
<source>Delete old database?</source>
<target state="translated">حذف قاعدة البيانات القديمة؟</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete pending connection" xml:space="preserve">
@@ -1125,8 +1142,9 @@
<target state="translated">حذف قائمة الانتظار</target>
<note>server test step</note>
</trans-unit>
<trans-unit id="Delete user profile?" xml:space="preserve">
<trans-unit id="Delete user profile?" xml:space="preserve" approved="no">
<source>Delete user profile?</source>
<target state="translated">حذف ملف تعريف المستخدم؟</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Description" xml:space="preserve" approved="no">
@@ -1134,8 +1152,9 @@
<target state="translated">الوصف</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Develop" xml:space="preserve">
<trans-unit id="Develop" xml:space="preserve" approved="no">
<source>Develop</source>
<target state="translated">يطور</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Developer tools" xml:space="preserve" approved="no">
@@ -1168,28 +1187,34 @@
<target state="translated">رسائل مباشرة</target>
<note>chat feature</note>
</trans-unit>
<trans-unit id="Direct messages between members are prohibited." xml:space="preserve">
<trans-unit id="Direct messages between members are prohibited." xml:space="preserve" approved="no">
<source>Direct messages between members are prohibited.</source>
<target state="translated">الرسائل المباشرة بين الأعضاء ممنوعة.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Disable SimpleX Lock" xml:space="preserve">
<trans-unit id="Disable SimpleX Lock" xml:space="preserve" approved="no">
<source>Disable SimpleX Lock</source>
<target state="translated">تعطيل قفل SimpleX</target>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Disappearing messages" xml:space="preserve">
<trans-unit id="Disappearing messages" xml:space="preserve" approved="no">
<source>Disappearing messages</source>
<target state="translated">الرسائل المختفية</target>
<note>chat feature</note>
</trans-unit>
<trans-unit id="Disappearing messages are prohibited in this chat." xml:space="preserve">
<trans-unit id="Disappearing messages are prohibited in this chat." xml:space="preserve" approved="no">
<source>Disappearing messages are prohibited in this chat.</source>
<target state="translated">يُحظر اختفاء الرسائل في هذه الدردشة.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Disappearing messages are prohibited." xml:space="preserve">
<trans-unit id="Disappearing messages are prohibited." xml:space="preserve" approved="no">
<source>Disappearing messages are prohibited.</source>
<target state="translated">الرسائل المختفية ممنوعة.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Disconnect" xml:space="preserve">
<trans-unit id="Disconnect" xml:space="preserve" approved="no">
<source>Disconnect</source>
<target state="translated">قطع الاتصال</target>
<note>server test step</note>
</trans-unit>
<trans-unit id="Display name" xml:space="preserve">
@@ -1200,12 +1225,14 @@
<source>Display name:</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve" approved="no">
<source>Do NOT use SimpleX for emergency calls.</source>
<target state="translated">لا تستخدم SimpleX لإجراء مكالمات الطوارئ.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do it later" xml:space="preserve">
<trans-unit id="Do it later" xml:space="preserve" approved="no">
<source>Do it later</source>
<target state="translated">افعل ذلك لاحقا</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Duplicate display name!" xml:space="preserve" approved="no">
@@ -1258,76 +1285,93 @@
<target state="translated">تفعيل الإشعارات دورية؟</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Encrypt" xml:space="preserve">
<trans-unit id="Encrypt" xml:space="preserve" approved="no">
<source>Encrypt</source>
<target state="translated">التشفير</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Encrypt database?" xml:space="preserve">
<trans-unit id="Encrypt database?" xml:space="preserve" approved="no">
<source>Encrypt database?</source>
<target state="translated">تشفير قاعدة البيانات؟</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Encrypted database" xml:space="preserve">
<trans-unit id="Encrypted database" xml:space="preserve" approved="no">
<source>Encrypted database</source>
<target state="translated">قاعدة بيانات مشفرة</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Encrypted message or another event" xml:space="preserve">
<trans-unit id="Encrypted message or another event" xml:space="preserve" approved="no">
<source>Encrypted message or another event</source>
<target state="translated">رسالة مشفرة أو حدث آخر</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: database error" xml:space="preserve">
<trans-unit id="Encrypted message: database error" xml:space="preserve" approved="no">
<source>Encrypted message: database error</source>
<target state="translated">رسالة مشفرة: خطأ في قاعدة البيانات</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: keychain error" xml:space="preserve">
<trans-unit id="Encrypted message: keychain error" xml:space="preserve" approved="no">
<source>Encrypted message: keychain error</source>
<target state="translated">رسالة مشفرة: خطأ في سلسلة المفاتيح</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: no passphrase" xml:space="preserve">
<trans-unit id="Encrypted message: no passphrase" xml:space="preserve" approved="no">
<source>Encrypted message: no passphrase</source>
<target state="translated">الرسالة المشفرة: لا توجد عبارة مرور</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: unexpected error" xml:space="preserve">
<trans-unit id="Encrypted message: unexpected error" xml:space="preserve" approved="no">
<source>Encrypted message: unexpected error</source>
<target state="translated">رسالة مشفرة: خطأ غير متوقع</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Enter correct passphrase." xml:space="preserve">
<trans-unit id="Enter correct passphrase." xml:space="preserve" approved="no">
<source>Enter correct passphrase.</source>
<target state="translated">أدخل عبارة المرور الصحيحة.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter passphrase…" xml:space="preserve">
<trans-unit id="Enter passphrase…" xml:space="preserve" approved="no">
<source>Enter passphrase…</source>
<target state="translated">أدخل عبارة المرور…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter server manually" xml:space="preserve">
<trans-unit id="Enter server manually" xml:space="preserve" approved="no">
<source>Enter server manually</source>
<target state="translated">أدخل الخادم يدوياً</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error" xml:space="preserve">
<trans-unit id="Error" xml:space="preserve" approved="no">
<source>Error</source>
<target state="translated">خطأ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error accepting contact request" xml:space="preserve">
<trans-unit id="Error accepting contact request" xml:space="preserve" approved="no">
<source>Error accepting contact request</source>
<target state="translated">خطأ في قبول طلب الاتصال</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error accessing database file" xml:space="preserve">
<source>Error accessing database file</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error adding member(s)" xml:space="preserve">
<trans-unit id="Error adding member(s)" xml:space="preserve" approved="no">
<source>Error adding member(s)</source>
<target state="translated">خطأ في إضافة عضو (أعضاء)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error changing address" xml:space="preserve">
<trans-unit id="Error changing address" xml:space="preserve" approved="no">
<source>Error changing address</source>
<target state="translated">خطأ في تغيير العنوان</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error changing role" xml:space="preserve">
<trans-unit id="Error changing role" xml:space="preserve" approved="no">
<source>Error changing role</source>
<target state="translated">خطأ في تغيير الدور المتغير</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error changing setting" xml:space="preserve">
<trans-unit id="Error changing setting" xml:space="preserve" approved="no">
<source>Error changing setting</source>
<target state="translated">خطأ في تغيير الإعدادات</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error creating address" xml:space="preserve">
@@ -5477,6 +5521,242 @@ This is your own one-time link!</source>
<source>Conditions will be automatically accepted for enabled operators on: %@.</source>
<target state="translated">سيتم قبول الشروط تلقائيًا للمشغلين الممكّنين على: %@.</target>
</trans-unit>
<trans-unit id="Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" xml:space="preserve" approved="no">
<source>Create new profile in [desktop app](https://simplex.chat/downloads/). 💻</source>
<target state="translated">أنشئ ملفًا شخصيًا جديدًا في [تطبيق سطح المكتب](https://simplex.chat/downloads/). 💻</target>
</trans-unit>
<trans-unit id="Error adding server" xml:space="preserve" approved="no">
<source>Error adding server</source>
<target state="translated">خطأ في إضافة الخادم</target>
</trans-unit>
<trans-unit id="Created at: %@" xml:space="preserve" approved="no">
<source>Created at: %@</source>
<target state="translated">تم الإنشاء في: %@</target>
</trans-unit>
<trans-unit id="Delete %lld messages of members?" xml:space="preserve" approved="no">
<source>Delete %lld messages of members?</source>
<target state="translated">حذف %lld الرسائل القديمة للأعضاء؟</target>
</trans-unit>
<trans-unit id="Disappearing message" xml:space="preserve" approved="no">
<source>Disappearing message</source>
<target state="translated">رسالة اختفاء</target>
</trans-unit>
<trans-unit id="Enabled" xml:space="preserve" approved="no">
<source>Enabled</source>
<target state="translated">ممكّنة</target>
</trans-unit>
<trans-unit id="Encrypted message: database migration error" xml:space="preserve" approved="no">
<source>Encrypted message: database migration error</source>
<target state="translated">رسالة مشفرة: خطأ في ترحيل قاعدة البيانات</target>
</trans-unit>
<trans-unit id="Delete list?" xml:space="preserve" approved="no">
<source>Delete list?</source>
<target state="translated">Delete list?</target>
</trans-unit>
<trans-unit id="Delivered even when Apple drops them." xml:space="preserve" approved="no">
<source>Delivered even when Apple drops them.</source>
<target state="translated">يتم تسليمها حتى عندما تسقطها شركة Apple.</target>
</trans-unit>
<trans-unit id="Destination server address of %@ is incompatible with forwarding server %@ settings." xml:space="preserve" approved="no">
<source>Destination server address of %@ is incompatible with forwarding server %@ settings.</source>
<target state="translated">عنوان خادم الوجهة %@ غير متوافق مع إعدادات خادم التوجيه %@.</target>
</trans-unit>
<trans-unit id="Destination server version of %@ is incompatible with forwarding server %@." xml:space="preserve" approved="no">
<source>Destination server version of %@ is incompatible with forwarding server %@.</source>
<target state="translated">إصدار خادم الوجهة لـ %@ غير متوافق مع خادم التوجيه %@.</target>
</trans-unit>
<trans-unit id="Don't create address" xml:space="preserve" approved="no">
<source>Don't create address</source>
<target state="translated">لا تنشئ عنوان</target>
</trans-unit>
<trans-unit id="Done" xml:space="preserve" approved="no">
<source>Done</source>
<target state="translated">تم</target>
</trans-unit>
<trans-unit id="Duration" xml:space="preserve" approved="no">
<source>Duration</source>
<target state="translated">المدة</target>
</trans-unit>
<trans-unit id="Encrypt local files" xml:space="preserve" approved="no">
<source>Encrypt local files</source>
<target state="translated">تشفير الملفات المحلية</target>
</trans-unit>
<trans-unit id="Encryption renegotiation in progress." xml:space="preserve" approved="no">
<source>Encryption renegotiation in progress.</source>
<target state="translated">إعادة التفاوض على التشفير قيد التنفيذ.</target>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve" approved="no">
<source>Enter Passcode</source>
<target state="translated">أدخل رمز المرور</target>
</trans-unit>
<trans-unit id="Enter passphrase" xml:space="preserve" approved="no">
<source>Enter passphrase</source>
<target state="translated">قم بأدخل عبارة المرور</target>
</trans-unit>
<trans-unit id="Enter welcome message…" xml:space="preserve" approved="no">
<source>Enter welcome message…</source>
<target state="translated">أدخل رسالة ترحيب…</target>
</trans-unit>
<trans-unit id="Enter your name…" xml:space="preserve" approved="no">
<source>Enter your name…</source>
<target state="translated">أدخل اسمك…</target>
</trans-unit>
<trans-unit id="Error changing to incognito!" xml:space="preserve" approved="no">
<source>Error changing to incognito!</source>
<target state="translated">خطأ في التغيير إلى التصفح المتخفي!</target>
</trans-unit>
<trans-unit id="Delete %lld messages?" xml:space="preserve" approved="no">
<source>Delete %lld messages?</source>
<target state="translated">حذف %lld رسائل؟</target>
</trans-unit>
<trans-unit id="Error aborting address change" xml:space="preserve" approved="no">
<source>Error aborting address change</source>
<target state="translated">خطأ في إجهاض تغيير العنوان</target>
</trans-unit>
<trans-unit id="Disappears at" xml:space="preserve" approved="no">
<source>Disappears at</source>
<target state="translated">يختفي عند</target>
</trans-unit>
<trans-unit id="Do not use credentials with proxy." xml:space="preserve" approved="no">
<source>Do not use credentials with proxy.</source>
<target state="translated">لا تستخدم بيانات الاعتماد مع البروكسي.</target>
</trans-unit>
<trans-unit id="Error accepting conditions" xml:space="preserve" approved="no">
<source>Error accepting conditions</source>
<target state="translated">خطأ في قبول الشروط</target>
</trans-unit>
<trans-unit id="Enter password above to show!" xml:space="preserve" approved="no">
<source>Enter password above to show!</source>
<target state="translated">أدخل كلمة المرور أعلاه للعرض!</target>
</trans-unit>
<trans-unit id="Error changing connection profile" xml:space="preserve" approved="no">
<source>Error changing connection profile</source>
<target state="translated">خطأ في تغيير ملف تعريف الاتصال</target>
</trans-unit>
<trans-unit id="Desktop app version %@ is not compatible with this app." xml:space="preserve" approved="no">
<source>Desktop app version %@ is not compatible with this app.</source>
<target state="translated">إصدار تطبيق سطح المكتب %@ غير متوافق مع هذا التطبيق.</target>
</trans-unit>
<trans-unit id="Encrypt stored files &amp; media" xml:space="preserve" approved="no">
<source>Encrypt stored files &amp; media</source>
<target state="translated">تشفير الملفات والوسائط المخزنة</target>
</trans-unit>
<trans-unit id="Enter this device name…" xml:space="preserve" approved="no">
<source>Enter this device name…</source>
<target state="translated">أدخل اسم الجهاز…</target>
</trans-unit>
<trans-unit id="Enter welcome message… (optional)" xml:space="preserve" approved="no">
<source>Enter welcome message… (optional)</source>
<target state="translated">أدخل رسالة ترحيب... (اختياري)</target>
</trans-unit>
<trans-unit id="Correct name to %@?" xml:space="preserve" approved="no">
<source>Correct name to %@?</source>
<target state="translated">الاسم الصحيح ل %@؟</target>
</trans-unit>
<trans-unit id="Delete member message?" xml:space="preserve" approved="no">
<source>Delete member message?</source>
<target state="translated">حذف رسالة العضو؟</target>
</trans-unit>
<trans-unit id="Disable automatic message deletion?" xml:space="preserve" approved="no">
<source>Disable automatic message deletion?</source>
<target state="translated">تعطيل حذف الرسائل التلقائي؟</target>
</trans-unit>
<trans-unit id="Disable delete messages" xml:space="preserve" approved="no">
<source>Disable delete messages</source>
<target state="translated">تعطيل حذف الرسائل</target>
</trans-unit>
<trans-unit id="Disable for all" xml:space="preserve" approved="no">
<source>Disable for all</source>
<target state="translated">تعطيل للجميع</target>
</trans-unit>
<trans-unit id="Disabled" xml:space="preserve" approved="no">
<source>Disabled</source>
<target state="translated">عاجز</target>
</trans-unit>
<trans-unit id="Documents:" xml:space="preserve" approved="no">
<source>Documents:</source>
<target state="translated">المستندات:</target>
</trans-unit>
<trans-unit id="By using SimpleX Chat you agree to:&#10;- send only legal content in public groups.&#10;- respect other users no spam." xml:space="preserve" approved="no">
<source>By using SimpleX Chat you agree to:
- send only legal content in public groups.
- respect other users no spam.</source>
<target state="translated">باستخدامك SimpleX Chat، فإنك توافق على:
- إرسال محتوى قانوني فقط في المجموعات العامة.
- احترام المستخدمين الآخرين - ممنوع إرسال رسائل مزعجة.</target>
</trans-unit>
<trans-unit id="Configure server operators" xml:space="preserve" approved="no">
<source>Configure server operators</source>
<target state="translated">تكوين مشغلي الخادم</target>
</trans-unit>
<trans-unit id="Enable Flux in Network &amp; servers settings for better metadata privacy." xml:space="preserve" approved="no">
<source>Enable Flux in Network &amp; servers settings for better metadata privacy.</source>
<target state="translated">تمكين التدفق في إعدادات الشبكة والخوادم لتحسين خصوصية البيانات الوصفية.</target>
</trans-unit>
<trans-unit id="Discover and join groups" xml:space="preserve" approved="no">
<source>Discover and join groups</source>
<target state="translated">اكتشف المجموعات وانضم إليها</target>
</trans-unit>
<trans-unit id="Discover via local network" xml:space="preserve" approved="no">
<source>Discover via local network</source>
<target state="translated">اكتشف عبر الشبكة المحلية</target>
</trans-unit>
<trans-unit id="Enabled for" xml:space="preserve" approved="no">
<source>Enabled for</source>
<target state="translated">ممكّن ل</target>
</trans-unit>
<trans-unit id="Encrypted message: app is stopped" xml:space="preserve" approved="no">
<source>Encrypted message: app is stopped</source>
<target state="translated">رسالة مشفرة: تم إيقاف التطبيق</target>
</trans-unit>
<trans-unit id="Enter group name…" xml:space="preserve" approved="no">
<source>Enter group name…</source>
<target state="translated">أدخل اسم المجموعة…</target>
</trans-unit>
<trans-unit id="Do NOT use private routing." xml:space="preserve" approved="no">
<source>Do NOT use private routing.</source>
<target state="translated">لا تستخدم التوجيه الخاص.</target>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve" approved="no">
<source>Encryption re-negotiation error</source>
<target state="translated">خطأ في إعادة تفاوض التشفير</target>
</trans-unit>
<trans-unit id="Connection with desktop stopped" xml:space="preserve" approved="no">
<source>Connection with desktop stopped</source>
<target state="translated">تم إيقاف الاتصال بسطح المكتب</target>
</trans-unit>
<trans-unit id="Destination server error: %@" xml:space="preserve" approved="no">
<source>Destination server error: %@</source>
<target state="translated">خطأ خادم الوجهة: %@</target>
</trans-unit>
<trans-unit id="Do NOT send messages directly, even if your or destination server does not support private routing." xml:space="preserve" approved="no">
<source>Do NOT send messages directly, even if your or destination server does not support private routing.</source>
<target state="translated">لا ترسل الرسائل بشكل مباشر، حتى لو كان خادمك أو خادم الوجهة لا يدعم التوجيه الخاص.</target>
</trans-unit>
<trans-unit id="Direct messages between members are prohibited in this chat." xml:space="preserve" approved="no">
<source>Direct messages between members are prohibited in this chat.</source>
<target state="translated">يُحظر إرسال الرسائل المباشرة بين الأعضاء في هذه الدردشة.</target>
</trans-unit>
<trans-unit id="Disconnect desktop?" xml:space="preserve" approved="no">
<source>Disconnect desktop?</source>
<target state="translated">فصل سطح المكتب؟</target>
</trans-unit>
<trans-unit id="Disable (keep overrides)" xml:space="preserve" approved="no">
<source>Disable (keep overrides)</source>
<target state="translated">تعطيل (الاحتفاظ بالتجاوزات)</target>
</trans-unit>
<trans-unit id="Disappears at: %@" xml:space="preserve" approved="no">
<source>Disappears at: %@</source>
<target state="translated">يختفي عند: %@</target>
</trans-unit>
<trans-unit id="Do not send history to new members." xml:space="preserve" approved="no">
<source>Do not send history to new members.</source>
<target state="translated">لا ترسل التاريخ إلى الأعضاء الجدد.</target>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve" approved="no">
<source>Encryption re-negotiation failed.</source>
<target state="translated">فشل إعادة التفاوض على التشفير.</target>
</trans-unit>
</body>
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="ar" datatype="plaintext">
@@ -778,6 +778,10 @@ swipe action</note>
<source>All reports will be archived for you.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>Всички ваши контакти ще останат свързани.</target>
@@ -1059,10 +1063,6 @@ swipe action</note>
<target>Архивиране на база данни</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>Прикачи</target>
@@ -5260,7 +5260,7 @@ Requires compatible VPN.</source>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<target>Отвори</target>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5290,23 +5290,15 @@ Requires compatible VPN.</source>
<target>Отвори група</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<target>Отвори миграцията към друго устройство</target>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<target>Приложението се отваря…</target>
@@ -7832,6 +7824,10 @@ To connect, please ask your contact to create another connection link and check
<source>Use TCP port %@ when no port is specified.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>Използвай чата</target>
@@ -8177,10 +8173,6 @@ To connect, please ask your contact to create another connection link and check
<source>XFTP server</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>**Не трябва** да използвате една и съща база данни на две устройства.</target>
@@ -9661,6 +9653,10 @@ last received msg: %2$@</source>
<source>%d new events</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<note>notification body</note>
@@ -9673,10 +9669,6 @@ last received msg: %2$@</source>
<source>New messages</source>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="bg" datatype="plaintext">
@@ -145,18 +145,22 @@
</trans-unit>
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
<source>%d file(s) are still being downloaded.</source>
<target>%d soubor(y) stále stahován(y).</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
<source>%d file(s) failed to download.</source>
<target>%d soubor(y) se nepodařilo stáhnout.</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
<source>%d file(s) were deleted.</source>
<target>%d soubor(y) smazán(y).</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
<source>%d file(s) were not downloaded.</source>
<target>%d soubor(y) nestažen(y).</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d hours" xml:space="preserve">
@@ -743,6 +747,10 @@ swipe action</note>
<source>All reports will be archived for you.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>Všechny vaše kontakty zůstanou připojeny.</target>
@@ -1008,10 +1016,6 @@ swipe action</note>
<source>Archiving database</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>Připojit</target>
@@ -5060,7 +5064,7 @@ Vyžaduje povolení sítě VPN.</target>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<target>Otevřít</target>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5089,22 +5093,14 @@ Vyžaduje povolení sítě VPN.</target>
<source>Open group</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<note>No comment provided by engineer.</note>
@@ -7560,6 +7556,10 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
<source>Use TCP port %@ when no port is specified.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>Použijte chat</target>
@@ -7885,10 +7885,6 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
<source>XFTP server</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<note>No comment provided by engineer.</note>
@@ -9323,6 +9319,10 @@ last received msg: %2$@</source>
<source>%d new events</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<note>notification body</note>
@@ -9335,10 +9335,6 @@ last received msg: %2$@</source>
<source>New messages</source>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="cs" datatype="plaintext">
@@ -796,6 +796,11 @@ swipe action</note>
<target>Alle Meldungen werden für Sie archiviert.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<target>Alle Server</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>Alle Ihre Kontakte bleiben verbunden.</target>
@@ -1086,11 +1091,6 @@ swipe action</note>
<target>Datenbank wird archiviert</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<target>Fragen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>Anhängen</target>
@@ -2195,7 +2195,7 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit>
<trans-unit id="Current profile" xml:space="preserve">
<source>Current profile</source>
<target>Aktueller Profil</target>
<target>Aktuelles Profil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Currently maximum supported file size is %@." xml:space="preserve">
@@ -5541,7 +5541,7 @@ Dies erfordert die Aktivierung eines VPNs.</target>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<target>Öffnen</target>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5573,26 +5573,15 @@ Dies erfordert die Aktivierung eines VPNs.</target>
<target>Gruppe öffnen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<target>Web-Link öffnen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<target>Web-Links aus der Chat-Liste öffnen</target>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<target>Migration auf ein anderes Gerät öffnen</target>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<target>Web-Link öffnen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<target>App wird geöffnet…</target>
@@ -7201,6 +7190,7 @@ chat item action</note>
</trans-unit>
<trans-unit id="Short link" xml:space="preserve">
<source>Short link</source>
<target>Verkürzter Link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Show QR code" xml:space="preserve">
@@ -7305,6 +7295,7 @@ chat item action</note>
</trans-unit>
<trans-unit id="SimpleX channel link" xml:space="preserve">
<source>SimpleX channel link</source>
<target>SimpleX-Kanal-Link</target>
<note>simplex link type</note>
</trans-unit>
<trans-unit id="SimpleX contact address" xml:space="preserve">
@@ -7899,6 +7890,7 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
</trans-unit>
<trans-unit id="This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link." xml:space="preserve">
<source>This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link.</source>
<target>Für diesen Link wird eine neuere App-Version benötigt. Bitte aktualisieren Sie die App oder bitten Sie Ihren Kontakt einen kompatiblen Link zu senden.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This link was used with another mobile device, please create a new link on the desktop." xml:space="preserve">
@@ -8202,6 +8194,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit>
<trans-unit id="Unsupported connection link" xml:space="preserve">
<source>Unsupported connection link</source>
<target>Verbindungs-Link wird nicht unterstützt</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve">
@@ -8299,6 +8292,11 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
<target>Solange kein Port konfiguriert ist, wird TCP-Port %@ genutzt.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<target>TCP-Port 443 nur für voreingestellte Server verwenden.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>Verwenden Sie Chat</target>
@@ -8366,6 +8364,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit>
<trans-unit id="Use short links (BETA)" xml:space="preserve">
<source>Use short links (BETA)</source>
<target>Kurze Links verwenden (BETA)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use the app while in the call." xml:space="preserve">
@@ -8663,11 +8662,6 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
<target>XFTP-Server</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<target>Ja</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>Sie dürfen die selbe Datenbank **nicht** auf zwei Geräten nutzen.</target>
@@ -10191,6 +10185,11 @@ Zuletzt empfangene Nachricht: %2$@</target>
<target>%d neue Ereignisse</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<target>Von %d Chat(s)</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<target>Von: %@</target>
@@ -10206,11 +10205,6 @@ Zuletzt empfangene Nachricht: %2$@</target>
<target>Neue Nachrichten</target>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<target>Neue Nachrichten in %d Chats</target>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="de" datatype="plaintext">
@@ -796,6 +796,11 @@ swipe action</note>
<target>All reports will be archived for you.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<target>All servers</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>All your contacts will remain connected.</target>
@@ -1086,11 +1091,6 @@ swipe action</note>
<target>Archiving database</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<target>Ask</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>Attach</target>
@@ -5541,7 +5541,7 @@ Requires compatible VPN.</target>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<target>Open</target>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5573,26 +5573,16 @@ Requires compatible VPN.</target>
<target>Open group</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<target>Open link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<target>Open links from chat list</target>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<target>Open link?</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<target>Open migration to another device</target>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<target>Open web link?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<target>Opening app…</target>
@@ -8303,6 +8293,11 @@ To connect, please ask your contact to create another connection link and check
<target>Use TCP port %@ when no port is specified.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<target>Use TCP port 443 for preset servers only.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>Use chat</target>
@@ -8668,11 +8663,6 @@ To connect, please ask your contact to create another connection link and check
<target>XFTP server</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<target>Yes</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>You **must not** use the same database on two devices.</target>
@@ -10196,6 +10186,11 @@ last received msg: %2$@</target>
<target>%d new events</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<target>From %d chat(s)</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<target>From: %@</target>
@@ -10211,11 +10206,6 @@ last received msg: %2$@</target>
<target>New messages</target>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<target>New messages in %d chats</target>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="en" datatype="plaintext">
@@ -796,6 +796,11 @@ swipe action</note>
<target>Todos los informes serán archivados para ti.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<target>Todos los servidores</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>Todos tus contactos permanecerán conectados.</target>
@@ -1086,11 +1091,6 @@ swipe action</note>
<target>Archivando base de datos</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<target>Preguntar</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>Adjuntar</target>
@@ -5541,7 +5541,7 @@ Requiere activación de la VPN.</target>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<target>Abrir</target>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5573,26 +5573,15 @@ Requiere activación de la VPN.</target>
<target>Grupo abierto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<target>Abrir enlace</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<target>Abrir enlaces desde listado de chats</target>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<target>Abrir menú migración a otro dispositivo</target>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<target>¿Abrir enlace web?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<target>Iniciando aplicación…</target>
@@ -7201,6 +7190,7 @@ chat item action</note>
</trans-unit>
<trans-unit id="Short link" xml:space="preserve">
<source>Short link</source>
<target>Enlace corto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Show QR code" xml:space="preserve">
@@ -7305,6 +7295,7 @@ chat item action</note>
</trans-unit>
<trans-unit id="SimpleX channel link" xml:space="preserve">
<source>SimpleX channel link</source>
<target>Enlace de canal SimpleX</target>
<note>simplex link type</note>
</trans-unit>
<trans-unit id="SimpleX contact address" xml:space="preserve">
@@ -7899,6 +7890,7 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida.</target>
</trans-unit>
<trans-unit id="This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link." xml:space="preserve">
<source>This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link.</source>
<target>Este enlace requiere una versión más reciente de la aplicación. Por favor, actualiza la aplicación o pide a tu contacto un enlace compatible.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This link was used with another mobile device, please create a new link on the desktop." xml:space="preserve">
@@ -8095,7 +8087,7 @@ Se te pedirá que completes la autenticación antes de activar esta función.</t
</trans-unit>
<trans-unit id="Unblock member for all?" xml:space="preserve">
<source>Unblock member for all?</source>
<target>¿Desbloquear miembro para todos?</target>
<target>¿Desbloquear el miembro para todos?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member?" xml:space="preserve">
@@ -8202,6 +8194,7 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión
</trans-unit>
<trans-unit id="Unsupported connection link" xml:space="preserve">
<source>Unsupported connection link</source>
<target>Enlace de conexión no compatible</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve">
@@ -8299,6 +8292,11 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión
<target>Se usa el puerto TCP %@ cuando no se ha especificado otro.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<target>Usar puerto TCP 443 solo en servidores predefinidos.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>Usar Chat</target>
@@ -8366,6 +8364,7 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión
</trans-unit>
<trans-unit id="Use short links (BETA)" xml:space="preserve">
<source>Use short links (BETA)</source>
<target>Usar enlaces cortos (BETA)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use the app while in the call." xml:space="preserve">
@@ -8663,11 +8662,6 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión
<target>Servidor XFTP</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<target>Si</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>**No debes** usar la misma base de datos en dos dispositivos.</target>
@@ -10191,6 +10185,11 @@ last received msg: %2$@</source>
<target>%d evento(s) nuevo(s)</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<target>De %d chat(s)</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<target>De: %@</target>
@@ -10206,11 +10205,6 @@ last received msg: %2$@</source>
<target>Mensajes nuevos</target>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<target>Mensajes nuevos en %d chat(s)</target>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="es" datatype="plaintext">
@@ -730,6 +730,10 @@ swipe action</note>
<source>All reports will be archived for you.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>Kaikki kontaktisi pysyvät yhteydessä.</target>
@@ -994,10 +998,6 @@ swipe action</note>
<source>Archiving database</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>Liitä</target>
@@ -5040,7 +5040,7 @@ Edellyttää VPN:n sallimista.</target>
</trans-unit>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5069,22 +5069,14 @@ Edellyttää VPN:n sallimista.</target>
<source>Open group</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<note>No comment provided by engineer.</note>
@@ -7537,6 +7529,10 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja
<source>Use TCP port %@ when no port is specified.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>Käytä chattia</target>
@@ -7862,10 +7858,6 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja
<source>XFTP server</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<note>No comment provided by engineer.</note>
@@ -9298,6 +9290,10 @@ last received msg: %2$@</source>
<source>%d new events</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<note>notification body</note>
@@ -9310,10 +9306,6 @@ last received msg: %2$@</source>
<source>New messages</source>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="fi" datatype="plaintext">
@@ -796,6 +796,10 @@ swipe action</note>
<target>Tous les rapports seront archivés pour vous.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>Tous vos contacts resteront connectés.</target>
@@ -1085,11 +1089,6 @@ swipe action</note>
<target>Archivage de la base de données</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<target>Demander</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>Attacher</target>
@@ -5506,7 +5505,7 @@ Nécessite l'activation d'un VPN.</target>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<target>Ouvrir</target>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5538,23 +5537,15 @@ Nécessite l'activation d'un VPN.</target>
<target>Ouvrir le groupe</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<target>Ouvrir le transfert vers un autre appareil</target>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<target>Ouverture de l'app…</target>
@@ -8227,6 +8218,10 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
<source>Use TCP port %@ when no port is specified.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>Utiliser le chat</target>
@@ -8590,10 +8585,6 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
<target>Serveur XFTP</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>Vous **ne devez pas** utiliser la même base de données sur deux appareils.</target>
@@ -10111,6 +10102,10 @@ dernier message reçu: %2$@</target>
<target>%d nouveaux événements</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<target>De : %@</target>
@@ -10126,11 +10121,6 @@ dernier message reçu: %2$@</target>
<target>Nouveaux messages</target>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<target>Nouveaux messages dans %d chats</target>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="fr" datatype="plaintext">
@@ -768,7 +768,7 @@ swipe action</note>
</trans-unit>
<trans-unit id="All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages." xml:space="preserve">
<source>All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages.</source>
<target>Az összes üzenet és fájl **végpontok közötti titkosítással**, a közvetlen üzenetek továbbá kvantumálló titkosítással is rendelkeznek.</target>
<target>Az összes üzenet és fájl **végpontok közötti titkosítással**, a közvetlen üzenetek továbbá kvantumbiztos titkosítással is rendelkeznek.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve">
@@ -796,6 +796,11 @@ swipe action</note>
<target>Az összes jelentés archiválva lesz az Ön számára.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<target>Összes kiszolgáló</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>Az összes partnerével kapcsolatban marad.</target>
@@ -1086,14 +1091,9 @@ swipe action</note>
<target>Adatbázis archiválása</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<target>Mindig kérdezzen rá</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>Csatolás</target>
<target>Mellékelés</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Audio &amp; video calls" xml:space="preserve">
@@ -4055,7 +4055,7 @@ Hiba: %2$@</target>
</trans-unit>
<trans-unit id="Hide:" xml:space="preserve">
<source>Hide:</source>
<target>Elrejtés:</target>
<target>Elrejtve:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="History" xml:space="preserve">
@@ -4942,12 +4942,12 @@ Ez a saját hivatkozása a(z) %@ nevű csoporthoz!</target>
</trans-unit>
<trans-unit id="Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." xml:space="preserve">
<source>Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery.</source>
<target>Az üzeneteket, fájlokat és hívásokat **végpontok közötti titkosítással**, sérülés utáni titkosság-védelemmel és -helyreállítással, továbbá visszautasítással védi.</target>
<target>Az üzenetek, a fájlok és a hívások **végpontok közötti titkosítással**, sérülés utáni titkosságvédelemmel és -helyreállítással, továbbá letagadhatósággal vannak védve.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Messages, files and calls are protected by **quantum resistant e2e encryption** with perfect forward secrecy, repudiation and break-in recovery." xml:space="preserve">
<source>Messages, files and calls are protected by **quantum resistant e2e encryption** with perfect forward secrecy, repudiation and break-in recovery.</source>
<target>Az üzenetek, fájlok és hívások **végpontok közötti kvantumálló titkosítással** sérülés utáni titkosságvédelemmel, visszautasítással és feltörés utáni helyreállítással vannak védve.</target>
<target>Az üzenetek, a fájlok és a hívások **végpontok közötti kvantumbiztos titkosítással**, sérülés utáni titkosságvédelemmel és -helyreállítással, továbbá letagadhatósággal vannak védve.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrate device" xml:space="preserve">
@@ -5541,7 +5541,7 @@ VPN engedélyezése szükséges.</target>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<target>Megnyitás</target>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5573,26 +5573,15 @@ VPN engedélyezése szükséges.</target>
<target>Csoport megnyitása</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<target>Hivatkozás megnyitása</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<target>Hivatkozás megnyitása a csevegési listából</target>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<target>Átköltöztetés indítása egy másik eszközre</target>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<target>Megnyitja a webhivatkozást?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<target>Az alkalmazás megnyitása…</target>
@@ -5906,7 +5895,7 @@ Hiba: %@</target>
</trans-unit>
<trans-unit id="Privacy redefined" xml:space="preserve">
<source>Privacy redefined</source>
<target>Adatvédelem újraértelmezve</target>
<target>Újraértelmezett adatvédelem</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Private chats, groups and your contacts are not accessible to server operators." xml:space="preserve">
@@ -6088,7 +6077,7 @@ Engedélyezze a *Hálózat és kiszolgálók* menüben.</target>
</trans-unit>
<trans-unit id="Quantum resistant encryption" xml:space="preserve">
<source>Quantum resistant encryption</source>
<target>Kvantumálló titkosítás</target>
<target>Kvantumbiztos titkosítás</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Rate the app" xml:space="preserve">
@@ -7201,6 +7190,7 @@ chat item action</note>
</trans-unit>
<trans-unit id="Short link" xml:space="preserve">
<source>Short link</source>
<target>Rövid hivatkozás</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Show QR code" xml:space="preserve">
@@ -7245,7 +7235,7 @@ chat item action</note>
</trans-unit>
<trans-unit id="Show:" xml:space="preserve">
<source>Show:</source>
<target>Megjelenítés:</target>
<target>Megjelenítve:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="SimpleX" xml:space="preserve">
@@ -7305,6 +7295,7 @@ chat item action</note>
</trans-unit>
<trans-unit id="SimpleX channel link" xml:space="preserve">
<source>SimpleX channel link</source>
<target>SimpleX-csatornahivatkozás</target>
<note>simplex link type</note>
</trans-unit>
<trans-unit id="SimpleX contact address" xml:space="preserve">
@@ -7864,7 +7855,7 @@ Ez valamilyen hiba vagy sérült kapcsolat esetén fordulhat elő.</target>
</trans-unit>
<trans-unit id="This chat is protected by quantum resistant end-to-end encryption." xml:space="preserve">
<source>This chat is protected by quantum resistant end-to-end encryption.</source>
<target>Ez a csevegés végpontok közötti kvantumálló titkosítással védett.</target>
<target>Ez a csevegés végpontok közötti kvantumbiztos titkosítással védett.</target>
<note>E2EE info chat item</note>
</trans-unit>
<trans-unit id="This device name" xml:space="preserve">
@@ -7899,6 +7890,7 @@ Ez valamilyen hiba vagy sérült kapcsolat esetén fordulhat elő.</target>
</trans-unit>
<trans-unit id="This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link." xml:space="preserve">
<source>This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link.</source>
<target>Ez a hivatkozás újabb alkalmazásverziót igényel. Frissítse az alkalmazást vagy kérjen egy kompatibilis hivatkozást a partnerétől.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This link was used with another mobile device, please create a new link on the desktop." xml:space="preserve">
@@ -8202,6 +8194,7 @@ A kapcsolódáshoz kérje meg a partnerét, hogy hozzon létre egy másik kapcso
</trans-unit>
<trans-unit id="Unsupported connection link" xml:space="preserve">
<source>Unsupported connection link</source>
<target>Nem támogatott kapcsolattartási hivatkozás</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve">
@@ -8299,6 +8292,11 @@ A kapcsolódáshoz kérje meg a partnerét, hogy hozzon létre egy másik kapcso
<target>A következő TCP-port használata, amikor nincs port megadva: %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<target>A 443-as TCP-port használata kizárólag az előre beállított kiszolgálokhoz.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>SimpleX Chat használata</target>
@@ -8366,6 +8364,7 @@ A kapcsolódáshoz kérje meg a partnerét, hogy hozzon létre egy másik kapcso
</trans-unit>
<trans-unit id="Use short links (BETA)" xml:space="preserve">
<source>Use short links (BETA)</source>
<target>Rövid hivatkozások használata (béta)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use the app while in the call." xml:space="preserve">
@@ -8440,7 +8439,7 @@ A kapcsolódáshoz kérje meg a partnerét, hogy hozzon létre egy másik kapcso
</trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve">
<source>Via secure quantum resistant protocol.</source>
<target>Biztonságos kvantumálló-protokollon keresztül.</target>
<target>Biztonságos kvantumbiztos protokollon keresztül.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video call" xml:space="preserve">
@@ -8663,11 +8662,6 @@ A kapcsolódáshoz kérje meg a partnerét, hogy hozzon létre egy másik kapcso
<target>XFTP-kiszolgáló</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<target>Igen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>**Nem szabad** ugyanazt az adatbázist használni egyszerre két eszközön.</target>
@@ -9808,7 +9802,7 @@ time to disappear</note>
</trans-unit>
<trans-unit id="quantum resistant e2e encryption" xml:space="preserve">
<source>quantum resistant e2e encryption</source>
<target>végpontok közötti kvantumálló titkosítás</target>
<target>végpontok közötti kvantumbiztos titkosítás</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="received answer…" xml:space="preserve">
@@ -10191,6 +10185,11 @@ utoljára fogadott üzenet: %2$@</target>
<target>%d új esemény</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<target>%d csevegésből</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<target>Tőle: %@</target>
@@ -10206,11 +10205,6 @@ utoljára fogadott üzenet: %2$@</target>
<target>Új üzenetek</target>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<target>Új üzenetek %d csevegésben</target>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="hu" datatype="plaintext">
@@ -796,6 +796,11 @@ swipe action</note>
<target>Tutte le segnalazioni verranno archiviate per te.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<target>Tutti i server</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>Tutti i tuoi contatti resteranno connessi.</target>
@@ -1086,11 +1091,6 @@ swipe action</note>
<target>Archiviazione del database</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<target>Chiedi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>Allega</target>
@@ -5541,7 +5541,7 @@ Richiede l'attivazione della VPN.</target>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<target>Apri</target>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5573,26 +5573,15 @@ Richiede l'attivazione della VPN.</target>
<target>Apri gruppo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<target>Apri link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<target>Apri i link dall'elenco delle chat</target>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<target>Apri migrazione ad un altro dispositivo</target>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<target>Aprire il link?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<target>Apertura dell'app…</target>
@@ -7201,6 +7190,7 @@ chat item action</note>
</trans-unit>
<trans-unit id="Short link" xml:space="preserve">
<source>Short link</source>
<target>Link breve</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Show QR code" xml:space="preserve">
@@ -7305,6 +7295,7 @@ chat item action</note>
</trans-unit>
<trans-unit id="SimpleX channel link" xml:space="preserve">
<source>SimpleX channel link</source>
<target>Link del canale SimpleX</target>
<note>simplex link type</note>
</trans-unit>
<trans-unit id="SimpleX contact address" xml:space="preserve">
@@ -7899,6 +7890,7 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.</ta
</trans-unit>
<trans-unit id="This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link." xml:space="preserve">
<source>This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link.</source>
<target>Questo link richiede una versione più recente dell'app. Aggiornala o chiedi al tuo contatto di inviare un link compatibile.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This link was used with another mobile device, please create a new link on the desktop." xml:space="preserve">
@@ -8202,6 +8194,7 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
</trans-unit>
<trans-unit id="Unsupported connection link" xml:space="preserve">
<source>Unsupported connection link</source>
<target>Link di connessione non supportato</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve">
@@ -8299,6 +8292,11 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
<target>Usa la porta TCP %@ quando non è specificata alcuna porta.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<target>Usa la porta TCP 443 solo per i server preimpostati.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>Usa la chat</target>
@@ -8366,6 +8364,7 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
</trans-unit>
<trans-unit id="Use short links (BETA)" xml:space="preserve">
<source>Use short links (BETA)</source>
<target>Usa link brevi (BETA)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use the app while in the call." xml:space="preserve">
@@ -8663,11 +8662,6 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
<target>Server XFTP</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<target>Sì</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>**Non devi** usare lo stesso database su due dispositivi.</target>
@@ -10191,6 +10185,11 @@ ultimo msg ricevuto: %2$@</target>
<target>%d nuovi eventi</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<target>Da %d chat</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<target>Da: %@</target>
@@ -10206,11 +10205,6 @@ ultimo msg ricevuto: %2$@</target>
<target>Nuovi messaggi</target>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<target>Nuovi messaggi in %d chat</target>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="it" datatype="plaintext">
@@ -768,6 +768,10 @@ swipe action</note>
<source>All reports will be archived for you.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>あなたの連絡先が繋がったまま継続します。</target>
@@ -1043,10 +1047,6 @@ swipe action</note>
<source>Archiving database</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>添付する</target>
@@ -5117,7 +5117,7 @@ VPN を有効にする必要があります。</target>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<target>開く</target>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5146,22 +5146,14 @@ VPN を有効にする必要があります。</target>
<source>Open group</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<note>No comment provided by engineer.</note>
@@ -7607,6 +7599,10 @@ To connect, please ask your contact to create another connection link and check
<source>Use TCP port %@ when no port is specified.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>チャット</target>
@@ -7932,10 +7928,6 @@ To connect, please ask your contact to create another connection link and check
<source>XFTP server</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<note>No comment provided by engineer.</note>
@@ -9369,6 +9361,10 @@ last received msg: %2$@</source>
<source>%d new events</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<note>notification body</note>
@@ -9381,10 +9377,6 @@ last received msg: %2$@</source>
<source>New messages</source>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="ja" datatype="plaintext">
@@ -796,6 +796,10 @@ swipe action</note>
<target>Alle rapporten worden voor u gearchiveerd.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>Al uw contacten blijven verbonden.</target>
@@ -1086,11 +1090,6 @@ swipe action</note>
<target>Database archiveren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<target>Vragen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>Bijvoegen</target>
@@ -5541,7 +5540,7 @@ Vereist het inschakelen van VPN.</target>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<target>Open</target>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5573,26 +5572,15 @@ Vereist het inschakelen van VPN.</target>
<target>Open groep</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<target>Link openen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<target>Open links van chatlijst</target>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<target>Open de migratie naar een ander apparaat</target>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<target>Weblink openen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<target>App openen…</target>
@@ -8299,6 +8287,10 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
<target>Gebruik TCP-poort %@ als er geen poort is opgegeven.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>Gebruik chat</target>
@@ -8663,11 +8655,6 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
<target>XFTP server</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<target>Ja</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>U **mag** niet dezelfde database op twee apparaten gebruiken.</target>
@@ -10191,6 +10178,10 @@ laatst ontvangen bericht: %2$@</target>
<target>%d nieuwe gebeurtenissen</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<target>Van: %@</target>
@@ -10206,11 +10197,6 @@ laatst ontvangen bericht: %2$@</target>
<target>Nieuwe berichten</target>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<target>Nieuwe berichten in %d chats</target>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="nl" datatype="plaintext">
@@ -796,6 +796,10 @@ swipe action</note>
<target>Wszystkie raporty zostaną dla Ciebie zarchiwizowane.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>Wszystkie Twoje kontakty pozostaną połączone.</target>
@@ -1086,11 +1090,6 @@ swipe action</note>
<target>Archiwizowanie bazy danych</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<target>Zapytaj</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>Dołącz</target>
@@ -5420,7 +5419,7 @@ Wymaga włączenia VPN.</target>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<target>Otwórz</target>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5450,23 +5449,15 @@ Wymaga włączenia VPN.</target>
<target>Grupa otwarta</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<target>Otwórz migrację na innym urządzeniu</target>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<target>Otwieranie aplikacji…</target>
@@ -8104,6 +8095,10 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
<source>Use TCP port %@ when no port is specified.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>Użyj czatu</target>
@@ -8461,10 +8456,6 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
<target>Serwer XFTP</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>**Nie możesz** używać tej samej bazy na dwóch urządzeniach.</target>
@@ -9975,6 +9966,10 @@ ostatnia otrzymana wiadomość: %2$@</target>
<source>%d new events</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<note>notification body</note>
@@ -9987,11 +9982,6 @@ ostatnia otrzymana wiadomość: %2$@</target>
<source>New messages</source>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<target>Nowe wiadomości w %d czatach</target>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="pl" datatype="plaintext">
@@ -796,6 +796,10 @@ swipe action</note>
<target>Все сообщения о нарушениях будут заархивированы для вас.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>Все контакты, которые соединились через этот адрес, сохранятся.</target>
@@ -1086,11 +1090,6 @@ swipe action</note>
<target>Подготовка архива</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<target>Спросить</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>Прикрепить</target>
@@ -5507,7 +5506,7 @@ Requires compatible VPN.</source>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<target>Открыть</target>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5539,26 +5538,15 @@ Requires compatible VPN.</source>
<target>Открыть группу</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<target>Открыть ссылку</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<target>Открыть ссылку из списка чатов</target>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<target>Открытие миграции на другое устройство</target>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<target>Открыть веб-ссылку?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<target>Приложение отрывается…</target>
@@ -8249,6 +8237,10 @@ To connect, please ask your contact to create another connection link and check
<target>Использовать TCP-порт %@, когда порт не указан.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>Использовать чат</target>
@@ -8613,11 +8605,6 @@ To connect, please ask your contact to create another connection link and check
<target>XFTP сервер</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<target>Да</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>Вы **не должны** использовать одну и ту же базу данных на двух устройствах.</target>
@@ -10135,6 +10122,10 @@ last received msg: %2$@</source>
<target>%d новых сообщений</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<target>От: %@</target>
@@ -10150,11 +10141,6 @@ last received msg: %2$@</source>
<target>Новые сообщения</target>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<target>Новые сообщения в %d разговоре(ах)</target>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="ru" datatype="plaintext">
@@ -722,6 +722,10 @@ swipe action</note>
<source>All reports will be archived for you.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>ผู้ติดต่อทั้งหมดของคุณจะยังคงเชื่อมต่ออยู่.</target>
@@ -986,10 +990,6 @@ swipe action</note>
<source>Archiving database</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>แนบ</target>
@@ -5019,7 +5019,7 @@ Requires compatible VPN.</source>
</trans-unit>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5048,22 +5048,14 @@ Requires compatible VPN.</source>
<source>Open group</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<note>No comment provided by engineer.</note>
@@ -7509,6 +7501,10 @@ To connect, please ask your contact to create another connection link and check
<source>Use TCP port %@ when no port is specified.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>ใช้แชท</target>
@@ -7832,10 +7828,6 @@ To connect, please ask your contact to create another connection link and check
<source>XFTP server</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<note>No comment provided by engineer.</note>
@@ -9265,6 +9257,10 @@ last received msg: %2$@</source>
<source>%d new events</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<note>notification body</note>
@@ -9277,10 +9273,6 @@ last received msg: %2$@</source>
<source>New messages</source>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="th" datatype="plaintext">
@@ -788,6 +788,10 @@ swipe action</note>
<source>All reports will be archived for you.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>Konuştuğun kişilerin tümü bağlı kalacaktır.</target>
@@ -1069,10 +1073,6 @@ swipe action</note>
<target>Veritabanı arşivleniyor</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>Ekle</target>
@@ -5432,7 +5432,7 @@ VPN'nin etkinleştirilmesi gerekir.</target>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<target>Aç</target>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5462,23 +5462,15 @@ VPN'nin etkinleştirilmesi gerekir.</target>
<target>Grubu aç</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<target>Başka bir cihaza açık geçiş</target>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<target>Uygulama açılıyor…</target>
@@ -8119,6 +8111,10 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste
<source>Use TCP port %@ when no port is specified.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>Sohbeti kullan</target>
@@ -8476,10 +8472,6 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste
<target>XFTP sunucusu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>Aynı veritabanını iki cihazda **kullanmamalısınız**.</target>
@@ -9989,6 +9981,10 @@ son alınan msj: %2$@</target>
<source>%d new events</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<note>notification body</note>
@@ -10001,10 +9997,6 @@ son alınan msj: %2$@</target>
<source>New messages</source>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="tr" datatype="plaintext">
@@ -788,6 +788,10 @@ swipe action</note>
<source>All reports will be archived for you.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All servers" xml:space="preserve">
<source>All servers</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>Всі ваші контакти залишаться на зв'язку.</target>
@@ -1069,10 +1073,6 @@ swipe action</note>
<target>Архівування бази даних</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ask" xml:space="preserve">
<source>Ask</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Attach" xml:space="preserve">
<source>Attach</source>
<target>Прикріпити</target>
@@ -5447,7 +5447,7 @@ Requires compatible VPN.</source>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<target>Відкрито</target>
<note>No comment provided by engineer.</note>
<note>alert action</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
<source>Open Settings</source>
@@ -5479,23 +5479,15 @@ Requires compatible VPN.</source>
<target>Відкрита група</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open link" xml:space="preserve">
<source>Open link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open links from chat list" xml:space="preserve">
<source>Open links from chat list</source>
<note>No comment provided by engineer.</note>
<trans-unit id="Open link?" xml:space="preserve">
<source>Open link?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Open migration to another device" xml:space="preserve">
<source>Open migration to another device</source>
<target>Відкрита міграція на інший пристрій</target>
<note>authentication reason</note>
</trans-unit>
<trans-unit id="Open web link?" xml:space="preserve">
<source>Open web link?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Opening app…" xml:space="preserve">
<source>Opening app…</source>
<target>Відкриваємо програму…</target>
@@ -8168,6 +8160,10 @@ To connect, please ask your contact to create another connection link and check
<source>Use TCP port %@ when no port is specified.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
<source>Use TCP port 443 for preset servers only.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use chat" xml:space="preserve">
<source>Use chat</source>
<target>Використовуйте чат</target>
@@ -8531,10 +8527,6 @@ To connect, please ask your contact to create another connection link and check
<target>XFTP-сервер</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Yes" xml:space="preserve">
<source>Yes</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>Ви **не повинні використовувати** одну і ту ж базу даних на двох пристроях.</target>
@@ -10052,6 +10044,10 @@ last received msg: %2$@</source>
<target>%d нових подій</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="From %d chat(s)" xml:space="preserve">
<source>From %d chat(s)</source>
<note>notification body</note>
</trans-unit>
<trans-unit id="From: %@" xml:space="preserve">
<source>From: %@</source>
<target>Від: %@</target>
@@ -10067,11 +10063,6 @@ last received msg: %2$@</source>
<target>Нові повідомлення</target>
<note>notification</note>
</trans-unit>
<trans-unit id="New messages in %d chats" xml:space="preserve">
<source>New messages in %d chats</source>
<target>Нові повідомлення в чатах %d</target>
<note>notification body</note>
</trans-unit>
</body>
</file>
<file original="SimpleX SE/en.lproj/InfoPlist.strings" source-language="en" target-language="uk" datatype="plaintext">
File diff suppressed because it is too large Load Diff
@@ -109,7 +109,7 @@
</trans-unit>
<trans-unit id="%d skipped message(s)" xml:space="preserve" approved="no">
<source>%d skipped message(s)</source>
<target state="translated">%d錯過了訊息</target>
<target state="translated">錯過的 %d 則訊息</target>
<note>integrity error chat item</note>
</trans-unit>
<trans-unit id="%lld" xml:space="preserve" approved="no">
@@ -124,17 +124,17 @@
</trans-unit>
<trans-unit id="%lld contact(s) selected" xml:space="preserve" approved="no">
<source>%lld contact(s) selected</source>
<target state="translated">%lld 已選擇聯絡人(s)</target>
<target state="translated">已選擇 %lld 個聯絡人</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld file(s) with total size of %@" xml:space="preserve" approved="no">
<source>%lld file(s) with total size of %@</source>
<target state="translated">%lld 檔案(s) 的總共大小%@</target>
<target state="translated">%lld 檔案總共大小 %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld members" xml:space="preserve" approved="no">
<source>%lld members</source>
<target state="translated">%lld 成員</target>
<target state="translated">%lld 成員</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld second(s)" xml:space="preserve" approved="no">
@@ -224,7 +224,7 @@
</trans-unit>
<trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve" approved="no">
<source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source>
<target state="translated">**警告**:即時推送訊息通知需要數據庫的密碼儲存在資料庫中。</target>
<target state="translated">**警告**:即時推送訊息通知需要數據庫的密碼儲存在資料庫中。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**e2e encrypted** audio call" xml:space="preserve" approved="no">
@@ -2704,12 +2704,12 @@ We will be adding server redundancy to prevent lost messages.</source>
</trans-unit>
<trans-unit id="Send link previews" xml:space="preserve" approved="no">
<source>Send link previews</source>
<target state="translated">傳送可以預覽的連結</target>
<target state="translated">傳送連結預覽</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Send live message" xml:space="preserve" approved="no">
<source>Send live message</source>
<target state="translated">傳送實況的訊息</target>
<target state="translated">傳送實訊息</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Send notifications" xml:space="preserve" approved="no">
@@ -2724,7 +2724,7 @@ We will be adding server redundancy to prevent lost messages.</source>
</trans-unit>
<trans-unit id="Send questions and ideas" xml:space="preserve" approved="no">
<source>Send questions and ideas</source>
<target state="translated">傳送問題和想法給開發者</target>
<target state="translated">給開發者提問題和想法</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Send them from gallery or custom keyboards." xml:space="preserve" approved="no">
@@ -2774,7 +2774,7 @@ We will be adding server redundancy to prevent lost messages.</source>
</trans-unit>
<trans-unit id="Set 1 day" xml:space="preserve" approved="no">
<source>Set 1 day</source>
<target state="translated">設定為1天</target>
<target state="translated">設定為 1 天</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Set contact name…" xml:space="preserve" approved="no">
@@ -3022,7 +3022,7 @@ We will be adding server redundancy to prevent lost messages.</source>
</trans-unit>
<trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve" approved="no">
<source>The connection you accepted will be cancelled!</source>
<target state="translated">你接受的連接將被取消!</target>
<target state="translated">你接受的連接將被取消!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The contact you shared this link with will NOT be able to connect!" xml:space="preserve" approved="no">
@@ -3061,7 +3061,7 @@ We will be adding server redundancy to prevent lost messages.</source>
</trans-unit>
<trans-unit id="The sender will NOT be notified" xml:space="preserve" approved="no">
<source>The sender will NOT be notified</source>
<target state="translated">發送者不會收到通知</target>
<target state="translated">發送者不會收到通知</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Theme" xml:space="preserve" approved="no">
@@ -3071,12 +3071,12 @@ We will be adding server redundancy to prevent lost messages.</source>
</trans-unit>
<trans-unit id="This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." xml:space="preserve" approved="no">
<source>This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain.</source>
<target state="translated">這操作不能還原 - 所有已經接收和傳送的檔案和媒體檔案將刪除。低解析度圖片將保留。</target>
<target state="translated">這操作不能還原 - 將刪除所有已經接收和傳送的檔案和媒體。將保留低解析度圖片。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This action cannot be undone - the messages sent and received earlier than selected will be deleted. It may take several minutes." xml:space="preserve" approved="no">
<source>This action cannot be undone - the messages sent and received earlier than selected will be deleted. It may take several minutes.</source>
<target state="translated">這操作無法撤銷 - 早於所選擇的時間發送和接收的訊息將被刪除。可能需要幾分鐘的時間。</target>
<target state="translated">這操作無法撤銷 - 早於所選時間的收發訊息將被刪除。可能需要幾分鐘。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This action cannot be undone - your profile, contacts, messages and files will be irreversibly lost." xml:space="preserve" approved="no">
@@ -3263,7 +3263,7 @@ To connect, please ask your contact to create another connection link and check
</trans-unit>
<trans-unit id="Use for new connections" xml:space="preserve" approved="no">
<source>Use for new connections</source>
<target state="translated">用於新的連</target>
<target state="translated">用於新的連</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve" approved="no">
@@ -3283,7 +3283,7 @@ To connect, please ask your contact to create another connection link and check
</trans-unit>
<trans-unit id="Verify connection security" xml:space="preserve" approved="no">
<source>Verify connection security</source>
<target state="translated">驗證連安全性</target>
<target state="translated">驗證連安全性</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Verify security code" xml:space="preserve" approved="no">
@@ -4163,7 +4163,7 @@ SimpleX 伺服器並不會看到你的個人檔案。</target>
</trans-unit>
<trans-unit id="via contact address link" xml:space="preserve" approved="no">
<source>via contact address link</source>
<target state="translated">透過聯絡人的邀請連結連</target>
<target state="translated">透過聯絡人的邀請連結連</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="via group link" xml:space="preserve" approved="no">
@@ -4173,7 +4173,7 @@ SimpleX 伺服器並不會看到你的個人檔案。</target>
</trans-unit>
<trans-unit id="via one-time link" xml:space="preserve" approved="no">
<source>via one-time link</source>
<target state="translated">透過一次性連結連</target>
<target state="translated">透過一次性連結連</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="via relay" xml:space="preserve" approved="no">
@@ -4702,7 +4702,7 @@ Available in v5.1</source>
</trans-unit>
<trans-unit id="%u messages failed to decrypt." xml:space="preserve" approved="no">
<source>%u messages failed to decrypt.</source>
<target state="translated">%u 訊息解密失敗。</target>
<target state="translated">%u 訊息解密失敗。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%u messages skipped." xml:space="preserve" approved="no">
@@ -5152,7 +5152,7 @@ Available in v5.1</source>
</trans-unit>
<trans-unit id="Tap to activate profile." xml:space="preserve" approved="no">
<source>Tap to activate profile.</source>
<target state="translated">點擊以激活配置檔案。</target>
<target state="translated">點擊以激活設定檔。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="There should be at least one visible user profile." xml:space="preserve" approved="no">
@@ -6034,7 +6034,7 @@ It can happen because of some bug or when the connection is compromised.</source
</trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve" approved="no">
<source>%lld messages marked deleted</source>
<target state="translated">%lld 訊息已刪除</target>
<target state="translated">%lld 訊息已標記為刪除</target>
</trans-unit>
<trans-unit id="Already connecting!" xml:space="preserve" approved="no">
<source>Already connecting!</source>
@@ -6046,7 +6046,7 @@ It can happen because of some bug or when the connection is compromised.</source
</trans-unit>
<trans-unit id="(new)" xml:space="preserve" approved="no">
<source>(new)</source>
<target state="translated">(新)</target>
<target state="translated">(新)</target>
</trans-unit>
<trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve" approved="no">
<source>%@, %@ and %lld other members connected</source>
@@ -6112,6 +6112,374 @@ It can happen because of some bug or when the connection is compromised.</source
<source>Background</source>
<target state="translated">後台</target>
</trans-unit>
<trans-unit id="SimpleX links not allowed" xml:space="preserve" approved="no">
<source>SimpleX links not allowed</source>
<target state="translated">不允許 SimpleX 連結</target>
</trans-unit>
<trans-unit id="Voice messages not allowed" xml:space="preserve" approved="no">
<source>Voice messages not allowed</source>
<target state="translated">不允許語音訊息</target>
</trans-unit>
<trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve" approved="no">
<source>The text you pasted is not a SimpleX link.</source>
<target state="translated">您貼在這裡的連結不是 SimpleX 連結。</target>
</trans-unit>
<trans-unit id="%d file(s) were deleted." xml:space="preserve" approved="no">
<source>%d file(s) were deleted.</source>
<target state="translated">已刪除 %d 個檔案。</target>
</trans-unit>
<trans-unit id="Reset to app theme" xml:space="preserve" approved="no">
<source>Reset to app theme</source>
<target state="translated">重設至應用程式主題</target>
</trans-unit>
<trans-unit id="Retry" xml:space="preserve" approved="no">
<source>Retry</source>
<target state="translated">重試</target>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve" approved="no">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<target state="translated">上傳的資料庫存檔將從伺服器永久移除。</target>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve" approved="no">
<source>Shape profile images</source>
<target state="translated">塑造個人資料圖片</target>
</trans-unit>
<trans-unit id="**Scan / Paste link**: to connect via a link you received." xml:space="preserve" approved="no">
<source>**Scan / Paste link**: to connect via a link you received.</source>
<target state="translated">**掃描/貼上連結**:以透過您收到的連結連線。</target>
</trans-unit>
<trans-unit id="Reports" xml:space="preserve" approved="no">
<source>Reports</source>
<target state="translated">舉報</target>
</trans-unit>
<trans-unit id="Use SOCKS proxy" xml:space="preserve" approved="no">
<source>Use SOCKS proxy</source>
<target state="translated">使用 SOCKS 代理</target>
</trans-unit>
<trans-unit id="Reset all statistics" xml:space="preserve" approved="no">
<source>Reset all statistics</source>
<target state="translated">重設所有統計數據</target>
</trans-unit>
<trans-unit id="SOCKS proxy" xml:space="preserve" approved="no">
<source>SOCKS proxy</source>
<target state="translated">SOCKS 代理</target>
</trans-unit>
<trans-unit id="Send message to enable calls." xml:space="preserve" approved="no">
<source>Send message to enable calls.</source>
<target state="translated">發送訊息以啟用通話功能。</target>
</trans-unit>
<trans-unit id="Send direct message to connect" xml:space="preserve" approved="no">
<source>Send direct message to connect</source>
<target state="translated">直接發送訊息以連結</target>
</trans-unit>
<trans-unit id="Scale" xml:space="preserve" approved="no">
<source>Scale</source>
<target state="translated">顯示比例</target>
</trans-unit>
<trans-unit id="Sent via proxy" xml:space="preserve" approved="no">
<source>Sent via proxy</source>
<target state="translated">通過代理發送</target>
</trans-unit>
<trans-unit id="Servers info" xml:space="preserve" approved="no">
<source>Servers info</source>
<target state="translated">伺服器訊息</target>
</trans-unit>
<trans-unit id="Set message expiration in chats." xml:space="preserve" approved="no">
<source>Set message expiration in chats.</source>
<target state="translated">設定聊天中訊息期限。</target>
</trans-unit>
<trans-unit id="Share SimpleX address on social media." xml:space="preserve" approved="no">
<source>Share SimpleX address on social media.</source>
<target state="translated">在社交媒體上分享 SimpleX 聯絡地址。</target>
</trans-unit>
<trans-unit id="Storage" xml:space="preserve" approved="no">
<source>Storage</source>
<target state="translated">存儲</target>
</trans-unit>
<trans-unit id="Starting from %@." xml:space="preserve" approved="no">
<source>Starting from %@.</source>
<target state="translated">開始於 %@。</target>
</trans-unit>
<trans-unit id="The second tick we missed! ✅" xml:space="preserve" approved="no">
<source>The second tick we missed! ✅</source>
<target state="translated">我們錯過的第二個勾選! ✅</target>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve" approved="no">
<source>Themes</source>
<target state="translated">主題</target>
</trans-unit>
<trans-unit id="%d file(s) failed to download." xml:space="preserve" approved="no">
<source>%d file(s) failed to download.</source>
<target state="translated">%d 個檔案下載失敗。</target>
</trans-unit>
<trans-unit id="Session code" xml:space="preserve" approved="no">
<source>Session code</source>
<target state="translated">會話代碼</target>
</trans-unit>
<trans-unit id="Servers statistics will be reset - this cannot be undone!" xml:space="preserve" approved="no">
<source>Servers statistics will be reset - this cannot be undone!</source>
<target state="translated">伺服器統計資料將被重設 - 此操作無法撤銷!</target>
</trans-unit>
<trans-unit id="**Create 1-time link**: to create and share a new invitation link." xml:space="preserve" approved="no">
<source>**Create 1-time link**: to create and share a new invitation link.</source>
<target state="translated">**建立一次性連結**:建立並分享新邀請連結。</target>
</trans-unit>
<trans-unit id="Set default theme" xml:space="preserve" approved="no">
<source>Set default theme</source>
<target state="translated">設定缺省主題</target>
</trans-unit>
<trans-unit id="%lld group events" xml:space="preserve" approved="no">
<source>%lld group events</source>
<target state="translated">%lld 個群組事件</target>
</trans-unit>
<trans-unit id="Reset all statistics?" xml:space="preserve" approved="no">
<source>Reset all statistics?</source>
<target state="translated">重設所有統計數據?</target>
</trans-unit>
<trans-unit id="%@ server" xml:space="preserve" approved="no">
<source>%@ server</source>
<target state="translated">%@ 伺服器</target>
</trans-unit>
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve" approved="no">
<source>%d file(s) were not downloaded.</source>
<target state="translated">%d 個檔案未下載。</target>
</trans-unit>
<trans-unit id="%d messages not forwarded" xml:space="preserve" approved="no">
<source>%d messages not forwarded</source>
<target state="translated">%d 則訊息未轉發</target>
</trans-unit>
<trans-unit id="Test notifications" xml:space="preserve" approved="no">
<source>Test notifications</source>
<target state="translated">测试通知</target>
</trans-unit>
<trans-unit id="(this device v%@)" xml:space="preserve" approved="no">
<source>(this device v%@)</source>
<target state="translated">(此設備 v%@</target>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve" approved="no">
<source>Settings were changed.</source>
<target state="translated">設定已更改。</target>
</trans-unit>
<trans-unit id="This action cannot be undone - the messages sent and received in this chat earlier than selected will be deleted." xml:space="preserve" approved="no">
<source>This action cannot be undone - the messages sent and received in this chat earlier than selected will be deleted.</source>
<target state="translated">這操作不能撤銷 - 此聊天中早於所選訊息的收發訊息將被刪除。</target>
</trans-unit>
<trans-unit id="Subscription errors" xml:space="preserve" approved="no">
<source>Subscription errors</source>
<target state="translated">訂閱錯誤</target>
</trans-unit>
<trans-unit id="Report" xml:space="preserve" approved="no">
<source>Report</source>
<target state="translated">舉報</target>
</trans-unit>
<trans-unit id="Send messages directly when IP address is protected and your or destination server does not support private routing." xml:space="preserve" approved="no">
<source>Send messages directly when IP address is protected and your or destination server does not support private routing.</source>
<target state="translated">當 IP 位址受保護且您或目的地伺服器不支援私人路由時,直接傳送訊息。</target>
</trans-unit>
<trans-unit id="Reset to user theme" xml:space="preserve" approved="no">
<source>Reset to user theme</source>
<target state="translated">重設為使用者主題</target>
</trans-unit>
<trans-unit id="Use short links (BETA)" xml:space="preserve" approved="no">
<source>Use short links (BETA)</source>
<target state="translated">使用短連結(Beta</target>
</trans-unit>
<trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve" approved="no">
<source>Up to 100 last messages are sent to new members.</source>
<target state="translated">最多 100 則最後的訊息會傳送至新成員。</target>
</trans-unit>
<trans-unit id="%d seconds(s)" xml:space="preserve" approved="no">
<source>%d seconds(s)</source>
<target state="translated">%d 秒</target>
</trans-unit>
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve" approved="no">
<source>%d file(s) are still being downloaded.</source>
<target state="translated">仍在下載 %d 個檔案。</target>
</trans-unit>
<trans-unit id="%lld messages blocked by admin" xml:space="preserve" approved="no">
<source>%lld messages blocked by admin</source>
<target state="translated">%lld 則訊息被管理員封鎖</target>
</trans-unit>
<trans-unit id="Report: %@" xml:space="preserve" approved="no">
<source>Report: %@</source>
<target state="translated">舉報:%@</target>
</trans-unit>
<trans-unit id="Review conditions" xml:space="preserve" approved="no">
<source>Review conditions</source>
<target state="translated">檢視使用條款</target>
</trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve" approved="no">
<source>Search or paste SimpleX link</source>
<target state="translated">搜尋或貼上 SimpleX 連結</target>
</trans-unit>
<trans-unit id="Sent directly" xml:space="preserve" approved="no">
<source>Sent directly</source>
<target state="translated">已直接發送</target>
</trans-unit>
<trans-unit id="SimpleX links are prohibited." xml:space="preserve" approved="no">
<source>SimpleX links are prohibited.</source>
<target state="translated">這群組禁止 SimpleX 連結。</target>
</trans-unit>
<trans-unit id="Uploaded files" xml:space="preserve" approved="no">
<source>Uploaded files</source>
<target state="translated">已上傳的檔案</target>
</trans-unit>
<trans-unit id="Use %@" xml:space="preserve" approved="no">
<source>Use %@</source>
<target state="translated">使用 %@</target>
</trans-unit>
<trans-unit id="Upload errors" xml:space="preserve" approved="no">
<source>Upload errors</source>
<target state="translated">上傳錯誤</target>
</trans-unit>
<trans-unit id="Use servers" xml:space="preserve" approved="no">
<source>Use servers</source>
<target state="translated">使用伺服器</target>
</trans-unit>
<trans-unit id="security code changed" xml:space="preserve" approved="no">
<source>security code changed</source>
<target state="translated">安全碼已變更</target>
</trans-unit>
<trans-unit id="These settings are for your current profile **%@**." xml:space="preserve" approved="no">
<source>These settings are for your current profile **%@**.</source>
<target state="translated">這些設定是針對您目前的設定檔 **%@**。</target>
</trans-unit>
<trans-unit id="They can be overridden in contact and group settings." xml:space="preserve" approved="no">
<source>They can be overridden in contact and group settings.</source>
<target state="translated">您可在連絡人和群組設定中覆寫它們。</target>
</trans-unit>
<trans-unit id="%@, %@" xml:space="preserve" approved="no">
<source>%1$@, %2$@</source>
<target state="translated">%1$@, %2$@</target>
</trans-unit>
<trans-unit id="Verify connections" xml:space="preserve" approved="no">
<source>Verify connections</source>
<target state="translated">驗證連線</target>
</trans-unit>
<trans-unit id="Verify connection" xml:space="preserve" approved="no">
<source>Verify connection</source>
<target state="translated">驗證連線</target>
</trans-unit>
<trans-unit id="Verify passphrase" xml:space="preserve" approved="no">
<source>Verify passphrase</source>
<target state="translated">驗證密碼</target>
</trans-unit>
<trans-unit id="Verify code with desktop" xml:space="preserve" approved="no">
<source>Verify code with desktop</source>
<target state="translated">使用桌上電腦驗證代碼</target>
</trans-unit>
<trans-unit id="Save list" xml:space="preserve" approved="no">
<source>Save list</source>
<target state="translated">儲存列表</target>
</trans-unit>
<trans-unit id="Saving %lld messages" xml:space="preserve" approved="no">
<source>Saving %lld messages</source>
<target state="translated">正在儲存 %lld 則訊息</target>
</trans-unit>
<trans-unit id="search" xml:space="preserve" approved="no">
<source>search</source>
<target state="translated">搜尋</target>
</trans-unit>
<trans-unit id="requested to connect" xml:space="preserve" approved="no">
<source>requested to connect</source>
<target state="translated">已請求連結</target>
</trans-unit>
<trans-unit id="saved" xml:space="preserve" approved="no">
<source>saved</source>
<target state="translated">已儲存</target>
</trans-unit>
<trans-unit id="video" xml:space="preserve" approved="no">
<source>video</source>
<target state="translated">視訊</target>
</trans-unit>
<trans-unit id="Tap to Connect" xml:space="preserve" approved="no">
<source>Tap to Connect</source>
<target state="translated">點擊以連結</target>
</trans-unit>
<trans-unit id="Unsupported connection link" xml:space="preserve" approved="no">
<source>Unsupported connection link</source>
<target state="translated">未受支持的連線連結</target>
</trans-unit>
<trans-unit id="Saved from" xml:space="preserve" approved="no">
<source>Saved from</source>
<target state="translated">儲存自</target>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve" approved="no">
<source>Saved</source>
<target state="translated">已儲存</target>
</trans-unit>
<trans-unit id="Scan / Paste link" xml:space="preserve" approved="no">
<source>Scan / Paste link</source>
<target state="translated">掃描/貼上連結</target>
</trans-unit>
<trans-unit id="SimpleX" xml:space="preserve" approved="no">
<source>SimpleX</source>
<target state="translated">SimpleX</target>
</trans-unit>
<trans-unit id="Use the app while in the call." xml:space="preserve" approved="no">
<source>Use the app while in the call.</source>
<target state="translated">在通話時使用此應用程式。</target>
</trans-unit>
<trans-unit id="v%@" xml:space="preserve" approved="no">
<source>v%@</source>
<target state="translated">v%@</target>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve" approved="no">
<source>Save your profile?</source>
<target state="translated">儲存設定檔?</target>
</trans-unit>
<trans-unit id="Use for messages" xml:space="preserve" approved="no">
<source>Use for messages</source>
<target state="translated">用於訊息</target>
</trans-unit>
<trans-unit id="Uploading archive" xml:space="preserve" approved="no">
<source>Uploading archive</source>
<target state="translated">正在上傳檔案庫</target>
</trans-unit>
<trans-unit id="Unlink" xml:space="preserve" approved="no">
<source>Unlink</source>
<target state="translated">從桌上電腦解除連結</target>
</trans-unit>
<trans-unit id="%lld messages blocked" xml:space="preserve" approved="no">
<source>%lld messages blocked</source>
<target state="translated">已封鎖 %d 則訊息</target>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve" approved="no">
<source>The same conditions will apply to operator **%@**.</source>
<target state="translated">相同條件也適用於 **%@** 操作員。</target>
</trans-unit>
<trans-unit id="These conditions will also apply for: **%@**." xml:space="preserve" approved="no">
<source>These conditions will also apply for: **%@**.</source>
<target state="translated">這些條件也適用於:**%@**。</target>
</trans-unit>
<trans-unit id="Upload failed" xml:space="preserve" approved="no">
<source>Upload failed</source>
<target state="translated">上傳失敗</target>
</trans-unit>
<trans-unit id="Use the app with one hand." xml:space="preserve" approved="no">
<source>Use the app with one hand.</source>
<target state="translated">單手使用此應用程式。</target>
</trans-unit>
<trans-unit id="Safely receive files" xml:space="preserve" approved="no">
<source>Safely receive files</source>
<target state="translated">安全地接收檔案</target>
</trans-unit>
<trans-unit id="Saved message" xml:space="preserve" approved="no">
<source>Saved message</source>
<target state="translated">已儲存的訊息</target>
</trans-unit>
<trans-unit id="Use from desktop" xml:space="preserve" approved="no">
<source>Use from desktop</source>
<target state="translated">在桌上電腦上使用</target>
</trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve" approved="no">
<source>Via secure quantum resistant protocol.</source>
<target state="translated">使用量子安全的協定。</target>
</trans-unit>
<trans-unit id="Uploaded" xml:space="preserve" approved="no">
<source>Uploaded</source>
<target state="translated">已上傳</target>
</trans-unit>
</body>
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="zh-Hant" datatype="plaintext">
@@ -1,6 +1,9 @@
/* notification body */
"%d new events" = "%d neue Ereignisse";
/* notification body */
"From %d chat(s)" = "Von %d Chat(s)";
/* notification body */
"From: %@" = "Von: %@";
@@ -10,6 +13,3 @@
/* notification */
"New messages" = "Neue Nachrichten";
/* notification body */
"New messages in %d chats" = "Neue Nachrichten in %d Chats";
@@ -1,6 +1,9 @@
/* notification body */
"%d new events" = "%d evento(s) nuevo(s)";
/* notification body */
"From %d chat(s)" = "De %d chat(s)";
/* notification body */
"From: %@" = "De: %@";
@@ -10,6 +13,3 @@
/* notification */
"New messages" = "Mensajes nuevos";
/* notification body */
"New messages in %d chats" = "Mensajes nuevos en %d chat(s)";
@@ -10,6 +10,3 @@
/* notification */
"New messages" = "Nouveaux messages";
/* notification body */
"New messages in %d chats" = "Nouveaux messages dans %d chats";
@@ -1,6 +1,9 @@
/* notification body */
"%d new events" = "%d új esemény";
/* notification body */
"From %d chat(s)" = "%d csevegésből";
/* notification body */
"From: %@" = "Tőle: %@";
@@ -10,6 +13,3 @@
/* notification */
"New messages" = "Új üzenetek";
/* notification body */
"New messages in %d chats" = "Új üzenetek %d csevegésben";
@@ -1,6 +1,9 @@
/* notification body */
"%d new events" = "%d nuovi eventi";
/* notification body */
"From %d chat(s)" = "Da %d chat";
/* notification body */
"From: %@" = "Da: %@";
@@ -10,6 +13,3 @@
/* notification */
"New messages" = "Nuovi messaggi";
/* notification body */
"New messages in %d chats" = "Nuovi messaggi in %d chat";
@@ -10,6 +10,3 @@
/* notification */
"New messages" = "Nieuwe berichten";
/* notification body */
"New messages in %d chats" = "Nieuwe berichten in %d chats";
@@ -10,6 +10,3 @@
/* notification */
"New messages" = "Новые сообщения";
/* notification body */
"New messages in %d chats" = "Новые сообщения в %d разговоре(ах)";
@@ -10,6 +10,3 @@
/* notification */
"New messages" = "Нові повідомлення";
/* notification body */
"New messages in %d chats" = "Нові повідомлення в чатах %d";
+1 -1
View File
@@ -160,7 +160,7 @@ struct ShareView: View {
}
}
@ViewBuilder private func linkPreview(_ linkPreview: LinkPreview) -> some View {
private func linkPreview(_ linkPreview: LinkPreview) -> some View {
previewArea {
HStack(alignment: .center, spacing: 8) {
if let uiImage = imageFromBase64(linkPreview.image) {
+18 -18
View File
@@ -179,8 +179,8 @@
64C3B0212A0D359700E19930 /* CustomTimePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */; };
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829982D54AEED006B9E89 /* libgmp.a */; };
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829992D54AEEE006B9E89 /* libffi.a */; };
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.3.1-5KR5yzeCZIzIubYi5BDCKe-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.3.1-5KR5yzeCZIzIubYi5BDCKe-ghc9.6.3.a */; };
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.3.3.1-5KR5yzeCZIzIubYi5BDCKe.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.3.1-5KR5yzeCZIzIubYi5BDCKe.a */; };
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.0-47rHZ52LFetD6j9vq8gwHM-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.0-47rHZ52LFetD6j9vq8gwHM-ghc9.6.3.a */; };
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.0-47rHZ52LFetD6j9vq8gwHM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.0-47rHZ52LFetD6j9vq8gwHM.a */; };
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299C2D54AEEE006B9E89 /* libgmpxx.a */; };
64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */; };
64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */; };
@@ -543,8 +543,8 @@
64C3B0202A0D359700E19930 /* CustomTimePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTimePicker.swift; sourceTree = "<group>"; };
64C829982D54AEED006B9E89 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
64C829992D54AEEE006B9E89 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.3.1-5KR5yzeCZIzIubYi5BDCKe-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.3.3.1-5KR5yzeCZIzIubYi5BDCKe-ghc9.6.3.a"; sourceTree = "<group>"; };
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.3.1-5KR5yzeCZIzIubYi5BDCKe.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.3.3.1-5KR5yzeCZIzIubYi5BDCKe.a"; sourceTree = "<group>"; };
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.0-47rHZ52LFetD6j9vq8gwHM-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.3.4.0-47rHZ52LFetD6j9vq8gwHM-ghc9.6.3.a"; sourceTree = "<group>"; };
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.0-47rHZ52LFetD6j9vq8gwHM.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.3.4.0-47rHZ52LFetD6j9vq8gwHM.a"; sourceTree = "<group>"; };
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
64D0C2BF29F9688300B38D5F /* UserAddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressView.swift; sourceTree = "<group>"; };
64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressLearnMore.swift; sourceTree = "<group>"; };
@@ -702,8 +702,8 @@
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */,
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */,
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */,
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.3.1-5KR5yzeCZIzIubYi5BDCKe-ghc9.6.3.a in Frameworks */,
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.3.3.1-5KR5yzeCZIzIubYi5BDCKe.a in Frameworks */,
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.0-47rHZ52LFetD6j9vq8gwHM-ghc9.6.3.a in Frameworks */,
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.0-47rHZ52LFetD6j9vq8gwHM.a in Frameworks */,
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -788,8 +788,8 @@
64C829992D54AEEE006B9E89 /* libffi.a */,
64C829982D54AEED006B9E89 /* libgmp.a */,
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */,
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.3.1-5KR5yzeCZIzIubYi5BDCKe-ghc9.6.3.a */,
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.3.1-5KR5yzeCZIzIubYi5BDCKe.a */,
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.0-47rHZ52LFetD6j9vq8gwHM-ghc9.6.3.a */,
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.0-47rHZ52LFetD6j9vq8gwHM.a */,
);
path = Libraries;
sourceTree = "<group>";
@@ -1981,7 +1981,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 274;
CURRENT_PROJECT_VERSION = 276;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -2031,7 +2031,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 274;
CURRENT_PROJECT_VERSION = 276;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -2073,7 +2073,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 274;
CURRENT_PROJECT_VERSION = 276;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
@@ -2093,7 +2093,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 274;
CURRENT_PROJECT_VERSION = 276;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
@@ -2118,7 +2118,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 274;
CURRENT_PROJECT_VERSION = 276;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GCC_OPTIMIZATION_LEVEL = s;
@@ -2155,7 +2155,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 274;
CURRENT_PROJECT_VERSION = 276;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_CODE_COVERAGE = NO;
@@ -2192,7 +2192,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 274;
CURRENT_PROJECT_VERSION = 276;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2243,7 +2243,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 274;
CURRENT_PROJECT_VERSION = 276;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2294,7 +2294,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 274;
CURRENT_PROJECT_VERSION = 276;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -2328,7 +2328,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 274;
CURRENT_PROJECT_VERSION = 276;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
+18 -12
View File
@@ -4137,18 +4137,16 @@ public enum FormatColor: String, Decodable, Hashable {
case black = "black"
case white = "white"
public var uiColor: Color {
get {
switch (self) {
case .red: return .red
case .green: return .green
case .blue: return .blue
case .yellow: return .yellow
case .cyan: return .cyan
case .magenta: return .purple
case .black: return .primary
case .white: return .primary
}
public var uiColor: Color? {
switch (self) {
case .red: .red
case .green: .green
case .blue: .blue
case .yellow: .yellow
case .cyan: .cyan
case .magenta: .purple
case .black: nil
case .white: nil
}
}
}
@@ -4173,6 +4171,14 @@ public enum ReportReason: Hashable {
case let .unknown(type): return type
}
}
public var attrString: NSAttributedString {
let descr = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
return NSAttributedString(string: text.isEmpty ? self.text : "\(self.text): ", attributes: [
.font: UIFont(descriptor: descr.withSymbolicTraits(.traitItalic) ?? descr, size: 0),
.foregroundColor: UIColor(Color.red)
])
}
}
extension ReportReason: Encodable {
+1 -1
View File
@@ -2825,7 +2825,7 @@ time to disappear */
/* No comment provided by engineer. */
"Only your contact can send voice messages." = "Само вашият контакт може да изпраща гласови съобщения.";
/* No comment provided by engineer. */
/* alert action */
"Open" = "Отвори";
/* No comment provided by engineer. */
+13 -1
View File
@@ -124,6 +124,18 @@
/* time interval */
"%d days" = "%d dní";
/* forward confirmation reason */
"%d file(s) are still being downloaded." = "%d soubor(y) stále stahován(y).";
/* forward confirmation reason */
"%d file(s) failed to download." = "%d soubor(y) se nepodařilo stáhnout.";
/* forward confirmation reason */
"%d file(s) were deleted." = "%d soubor(y) smazán(y).";
/* forward confirmation reason */
"%d file(s) were not downloaded." = "%d soubor(y) nestažen(y).";
/* time interval */
"%d hours" = "%d hodin";
@@ -2205,7 +2217,7 @@ time to disappear */
/* No comment provided by engineer. */
"Only your contact can send voice messages." = "Hlasové zprávy může odesílat pouze váš kontakt.";
/* No comment provided by engineer. */
/* alert action */
"Open" = "Otevřít";
/* No comment provided by engineer. */
+23 -17
View File
@@ -505,6 +505,9 @@ swipe action */
/* No comment provided by engineer. */
"All reports will be archived for you." = "Alle Meldungen werden für Sie archiviert.";
/* No comment provided by engineer. */
"All servers" = "Alle Server";
/* No comment provided by engineer. */
"All your contacts will remain connected." = "Alle Ihre Kontakte bleiben verbunden.";
@@ -688,9 +691,6 @@ swipe action */
/* No comment provided by engineer. */
"Archiving database" = "Datenbank wird archiviert";
/* No comment provided by engineer. */
"Ask" = "Fragen";
/* No comment provided by engineer. */
"Attach" = "Anhängen";
@@ -1460,7 +1460,7 @@ set passcode view */
"Current passphrase…" = "Aktuelles Passwort…";
/* No comment provided by engineer. */
"Current profile" = "Aktueller Profil";
"Current profile" = "Aktuelles Profil";
/* No comment provided by engineer. */
"Currently maximum supported file size is %@." = "Die derzeit maximal unterstützte Dateigröße beträgt %@.";
@@ -3677,7 +3677,7 @@ time to disappear */
/* No comment provided by engineer. */
"Only your contact can send voice messages." = "Nur Ihr Kontakt kann Sprachnachrichten versenden.";
/* No comment provided by engineer. */
/* alert action */
"Open" = "Öffnen";
/* No comment provided by engineer. */
@@ -3695,21 +3695,12 @@ time to disappear */
/* No comment provided by engineer. */
"Open group" = "Gruppe öffnen";
/* No comment provided by engineer. */
"Open link" = "Web-Link öffnen";
/* No comment provided by engineer. */
"Open links from chat list" = "Web-Links aus der Chat-Liste öffnen";
/* authentication reason */
"Open migration to another device" = "Migration auf ein anderes Gerät öffnen";
/* No comment provided by engineer. */
"Open Settings" = "Geräte-Einstellungen öffnen";
/* No comment provided by engineer. */
"Open web link?" = "Web-Link öffnen?";
/* No comment provided by engineer. */
"Opening app…" = "App wird geöffnet…";
@@ -4751,6 +4742,9 @@ chat item action */
/* No comment provided by engineer. */
"Share with contacts" = "Mit Kontakten teilen";
/* No comment provided by engineer. */
"Short link" = "Verkürzter Link";
/* No comment provided by engineer. */
"Show → on messages sent via private routing." = "Bei Nachrichten, die über privates Routing versendet wurden, → anzeigen.";
@@ -4793,6 +4787,9 @@ chat item action */
/* No comment provided by engineer. */
"SimpleX address or 1-time link?" = "SimpleX-Adresse oder Einmal-Link?";
/* simplex link type */
"SimpleX channel link" = "SimpleX-Kanal-Link";
/* No comment provided by engineer. */
"SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app." = "SimpleX-Chat und Flux haben vereinbart, die von Flux betriebenen Server in die App aufzunehmen.";
@@ -5181,6 +5178,9 @@ report reason */
/* No comment provided by engineer. */
"This is your own SimpleX address!" = "Das ist Ihre eigene SimpleX-Adresse!";
/* No comment provided by engineer. */
"This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link." = "Für diesen Link wird eine neuere App-Version benötigt. Bitte aktualisieren Sie die App oder bitten Sie Ihren Kontakt einen kompatiblen Link zu senden.";
/* No comment provided by engineer. */
"This link was used with another mobile device, please create a new link on the desktop." = "Dieser Link wurde schon mit einem anderen Mobiltelefon genutzt. Bitte erstellen sie einen neuen Link in der Desktop-App.";
@@ -5373,6 +5373,9 @@ report reason */
/* swipe action */
"Unread" = "Ungelesen";
/* No comment provided by engineer. */
"Unsupported connection link" = "Verbindungs-Link wird nicht unterstützt";
/* No comment provided by engineer. */
"Up to 100 last messages are sent to new members." = "Bis zu 100 der letzten Nachrichten werden an neue Mitglieder gesendet.";
@@ -5466,6 +5469,9 @@ report reason */
/* No comment provided by engineer. */
"Use servers" = "Verwende Server";
/* No comment provided by engineer. */
"Use short links (BETA)" = "Kurze Links verwenden (BETA)";
/* No comment provided by engineer. */
"Use SimpleX Chat servers?" = "Verwenden Sie SimpleX-Chat-Server?";
@@ -5475,6 +5481,9 @@ report reason */
/* No comment provided by engineer. */
"Use TCP port %@ when no port is specified." = "Solange kein Port konfiguriert ist, wird TCP-Port %@ genutzt.";
/* No comment provided by engineer. */
"Use TCP port 443 for preset servers only." = "TCP-Port 443 nur für voreingestellte Server verwenden.";
/* No comment provided by engineer. */
"Use the app while in the call." = "Die App kann während eines Anrufs genutzt werden.";
@@ -5694,9 +5703,6 @@ report reason */
/* pref value */
"yes" = "Ja";
/* No comment provided by engineer. */
"Yes" = "Ja";
/* No comment provided by engineer. */
"you" = "Profil";
+23 -17
View File
@@ -505,6 +505,9 @@ swipe action */
/* No comment provided by engineer. */
"All reports will be archived for you." = "Todos los informes serán archivados para ti.";
/* No comment provided by engineer. */
"All servers" = "Todos los servidores";
/* No comment provided by engineer. */
"All your contacts will remain connected." = "Todos tus contactos permanecerán conectados.";
@@ -688,9 +691,6 @@ swipe action */
/* No comment provided by engineer. */
"Archiving database" = "Archivando base de datos";
/* No comment provided by engineer. */
"Ask" = "Preguntar";
/* No comment provided by engineer. */
"Attach" = "Adjuntar";
@@ -3677,7 +3677,7 @@ time to disappear */
/* No comment provided by engineer. */
"Only your contact can send voice messages." = "Sólo tu contacto puede enviar mensajes de voz.";
/* No comment provided by engineer. */
/* alert action */
"Open" = "Abrir";
/* No comment provided by engineer. */
@@ -3695,21 +3695,12 @@ time to disappear */
/* No comment provided by engineer. */
"Open group" = "Grupo abierto";
/* No comment provided by engineer. */
"Open link" = "Abrir enlace";
/* No comment provided by engineer. */
"Open links from chat list" = "Abrir enlaces desde listado de chats";
/* authentication reason */
"Open migration to another device" = "Abrir menú migración a otro dispositivo";
/* No comment provided by engineer. */
"Open Settings" = "Abrir Configuración";
/* No comment provided by engineer. */
"Open web link?" = "¿Abrir enlace web?";
/* No comment provided by engineer. */
"Opening app…" = "Iniciando aplicación…";
@@ -4751,6 +4742,9 @@ chat item action */
/* No comment provided by engineer. */
"Share with contacts" = "Compartir con contactos";
/* No comment provided by engineer. */
"Short link" = "Enlace corto";
/* No comment provided by engineer. */
"Show → on messages sent via private routing." = "Mostrar → en mensajes con enrutamiento privado.";
@@ -4793,6 +4787,9 @@ chat item action */
/* No comment provided by engineer. */
"SimpleX address or 1-time link?" = "¿Dirección SimpleX o enlace de un uso?";
/* simplex link type */
"SimpleX channel link" = "Enlace de canal SimpleX";
/* No comment provided by engineer. */
"SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app." = "Simplex Chat y Flux han acordado incluir en la aplicación servidores operados por Flux.";
@@ -5181,6 +5178,9 @@ report reason */
/* No comment provided by engineer. */
"This is your own SimpleX address!" = "¡Esta es tu propia dirección SimpleX!";
/* No comment provided by engineer. */
"This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link." = "Este enlace requiere una versión más reciente de la aplicación. Por favor, actualiza la aplicación o pide a tu contacto un enlace compatible.";
/* No comment provided by engineer. */
"This link was used with another mobile device, please create a new link on the desktop." = "Este enlace ha sido usado en otro dispositivo móvil, por favor crea un enlace nuevo en el ordenador.";
@@ -5296,7 +5296,7 @@ report reason */
"Unblock member" = "Desbloquear miembro";
/* No comment provided by engineer. */
"Unblock member for all?" = "¿Desbloquear miembro para todos?";
"Unblock member for all?" = "¿Desbloquear el miembro para todos?";
/* No comment provided by engineer. */
"Unblock member?" = "¿Desbloquear miembro?";
@@ -5373,6 +5373,9 @@ report reason */
/* swipe action */
"Unread" = "No leído";
/* No comment provided by engineer. */
"Unsupported connection link" = "Enlace de conexión no compatible";
/* No comment provided by engineer. */
"Up to 100 last messages are sent to new members." = "Hasta 100 últimos mensajes son enviados a los miembros nuevos.";
@@ -5466,6 +5469,9 @@ report reason */
/* No comment provided by engineer. */
"Use servers" = "Usar servidores";
/* No comment provided by engineer. */
"Use short links (BETA)" = "Usar enlaces cortos (BETA)";
/* No comment provided by engineer. */
"Use SimpleX Chat servers?" = "¿Usar servidores SimpleX Chat?";
@@ -5475,6 +5481,9 @@ report reason */
/* No comment provided by engineer. */
"Use TCP port %@ when no port is specified." = "Se usa el puerto TCP %@ cuando no se ha especificado otro.";
/* No comment provided by engineer. */
"Use TCP port 443 for preset servers only." = "Usar puerto TCP 443 solo en servidores predefinidos.";
/* No comment provided by engineer. */
"Use the app while in the call." = "Usar la aplicación durante la llamada.";
@@ -5694,9 +5703,6 @@ report reason */
/* pref value */
"yes" = "sí";
/* No comment provided by engineer. */
"Yes" = "Si";
/* No comment provided by engineer. */
"you" = "tu";
+1 -4
View File
@@ -682,9 +682,6 @@ swipe action */
/* No comment provided by engineer. */
"Archiving database" = "Archivage de la base de données";
/* No comment provided by engineer. */
"Ask" = "Demander";
/* No comment provided by engineer. */
"Attach" = "Attacher";
@@ -3566,7 +3563,7 @@ time to disappear */
/* No comment provided by engineer. */
"Only your contact can send voice messages." = "Seul votre contact peut envoyer des messages vocaux.";
/* No comment provided by engineer. */
/* alert action */
"Open" = "Ouvrir";
/* No comment provided by engineer. */
+33 -27
View File
@@ -488,7 +488,7 @@ swipe action */
"all members" = "összes tag";
/* No comment provided by engineer. */
"All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages." = "Az összes üzenet és fájl **végpontok közötti titkosítással**, a közvetlen üzenetek továbbá kvantumálló titkosítással is rendelkeznek.";
"All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages." = "Az összes üzenet és fájl **végpontok közötti titkosítással**, a közvetlen üzenetek továbbá kvantumbiztos titkosítással is rendelkeznek.";
/* No comment provided by engineer. */
"All messages will be deleted - this cannot be undone!" = "Az összes üzenet törölve lesz ez a művelet nem vonható vissza!";
@@ -505,6 +505,9 @@ swipe action */
/* No comment provided by engineer. */
"All reports will be archived for you." = "Az összes jelentés archiválva lesz az Ön számára.";
/* No comment provided by engineer. */
"All servers" = "Összes kiszolgáló";
/* No comment provided by engineer. */
"All your contacts will remain connected." = "Az összes partnerével kapcsolatban marad.";
@@ -689,10 +692,7 @@ swipe action */
"Archiving database" = "Adatbázis archiválása";
/* No comment provided by engineer. */
"Ask" = "Mindig kérdezzen rá";
/* No comment provided by engineer. */
"Attach" = "Csatolás";
"Attach" = "Mellékelés";
/* No comment provided by engineer. */
"attempts" = "próbálkozások";
@@ -2671,7 +2671,7 @@ snd error text */
"Hide profile" = "Profil elrejtése";
/* No comment provided by engineer. */
"Hide:" = "Elrejtés:";
"Hide:" = "Elrejtve:";
/* No comment provided by engineer. */
"History" = "Előzmények";
@@ -3274,10 +3274,10 @@ snd error text */
"Messages were deleted after you selected them." = "Az üzeneteket törölték miután kijelölte őket.";
/* No comment provided by engineer. */
"Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." = "Az üzeneteket, fájlokat és hívásokat **végpontok közötti titkosítással**, sérülés utáni titkosság-védelemmel és -helyreállítással, továbbá visszautasítással védi.";
"Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." = "Az üzenetek, a fájlok és a hívások **végpontok közötti titkosítással**, sérülés utáni titkosságvédelemmel és -helyreállítással, továbbá letagadhatósággal vannak védve.";
/* No comment provided by engineer. */
"Messages, files and calls are protected by **quantum resistant e2e encryption** with perfect forward secrecy, repudiation and break-in recovery." = "Az üzenetek, fájlok és hívások **végpontok közötti kvantumálló titkosítással** sérülés utáni titkosságvédelemmel, visszautasítással és feltörés utáni helyreállítással vannak védve.";
"Messages, files and calls are protected by **quantum resistant e2e encryption** with perfect forward secrecy, repudiation and break-in recovery." = "Az üzenetek, a fájlok és a hívások **végpontok közötti kvantumbiztos titkosítással**, sérülés utáni titkosságvédelemmel és -helyreállítással, továbbá letagadhatósággal vannak védve.";
/* No comment provided by engineer. */
"Migrate device" = "Eszköz átköltöztetése";
@@ -3677,7 +3677,7 @@ time to disappear */
/* No comment provided by engineer. */
"Only your contact can send voice messages." = "Csak a partnere tud hangüzeneteket küldeni.";
/* No comment provided by engineer. */
/* alert action */
"Open" = "Megnyitás";
/* No comment provided by engineer. */
@@ -3695,21 +3695,12 @@ time to disappear */
/* No comment provided by engineer. */
"Open group" = "Csoport megnyitása";
/* No comment provided by engineer. */
"Open link" = "Hivatkozás megnyitása";
/* No comment provided by engineer. */
"Open links from chat list" = "Hivatkozás megnyitása a csevegési listából";
/* authentication reason */
"Open migration to another device" = "Átköltöztetés indítása egy másik eszközre";
/* No comment provided by engineer. */
"Open Settings" = "Beállítások megnyitása";
/* No comment provided by engineer. */
"Open web link?" = "Megnyitja a webhivatkozást?";
/* No comment provided by engineer. */
"Opening app…" = "Az alkalmazás megnyitása…";
@@ -3915,7 +3906,7 @@ time to disappear */
"Privacy policy and conditions of use." = "Adatvédelmi szabályzat és felhasználási feltételek.";
/* No comment provided by engineer. */
"Privacy redefined" = "Adatvédelem újraértelmezve";
"Privacy redefined" = "Újraértelmezett adatvédelem";
/* No comment provided by engineer. */
"Private chats, groups and your contacts are not accessible to server operators." = "A privát csevegések, a csoportok és a partnerek nem érhetők el a szerver üzemeltetői számára.";
@@ -4023,10 +4014,10 @@ time to disappear */
"Push server" = "Push-kiszolgáló";
/* chat item text */
"quantum resistant e2e encryption" = "végpontok közötti kvantumálló titkosítás";
"quantum resistant e2e encryption" = "végpontok közötti kvantumbiztos titkosítás";
/* No comment provided by engineer. */
"Quantum resistant encryption" = "Kvantumálló titkosítás";
"Quantum resistant encryption" = "Kvantumbiztos titkosítás";
/* No comment provided by engineer. */
"Rate the app" = "Értékelje az alkalmazást";
@@ -4751,6 +4742,9 @@ chat item action */
/* No comment provided by engineer. */
"Share with contacts" = "Megosztás a partnerekkel";
/* No comment provided by engineer. */
"Short link" = "Rövid hivatkozás";
/* No comment provided by engineer. */
"Show → on messages sent via private routing." = "Egy „→” jel megjelenítése a privát útválasztáson keresztül küldött üzeneteknél.";
@@ -4776,7 +4770,7 @@ chat item action */
"Show QR code" = "QR-kód megjelenítése";
/* No comment provided by engineer. */
"Show:" = "Megjelenítés:";
"Show:" = "Megjelenítve:";
/* No comment provided by engineer. */
"SimpleX" = "SimpleX";
@@ -4793,6 +4787,9 @@ chat item action */
/* No comment provided by engineer. */
"SimpleX address or 1-time link?" = "SimpleX-cím vagy egyszer használható meghívó?";
/* simplex link type */
"SimpleX channel link" = "SimpleX-csatornahivatkozás";
/* No comment provided by engineer. */
"SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app." = "A SimpleX Chat és a Flux megállapodást kötött arról, hogy a Flux által üzemeltetett kiszolgálókat beépítik az alkalmazásba.";
@@ -5158,7 +5155,7 @@ report reason */
"This chat is protected by end-to-end encryption." = "Ez a csevegés végpontok közötti titkosítással védett.";
/* E2EE info chat item */
"This chat is protected by quantum resistant end-to-end encryption." = "Ez a csevegés végpontok közötti kvantumálló titkosítással védett.";
"This chat is protected by quantum resistant end-to-end encryption." = "Ez a csevegés végpontok közötti kvantumbiztos titkosítással védett.";
/* notification title */
"this contact" = "ez a partner";
@@ -5181,6 +5178,9 @@ report reason */
/* No comment provided by engineer. */
"This is your own SimpleX address!" = "Ez a saját SimpleX-címe!";
/* No comment provided by engineer. */
"This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link." = "Ez a hivatkozás újabb alkalmazásverziót igényel. Frissítse az alkalmazást vagy kérjen egy kompatibilis hivatkozást a partnerétől.";
/* No comment provided by engineer. */
"This link was used with another mobile device, please create a new link on the desktop." = "Ezt a hivatkozást egy másik hordozható eszközön már használták, hozzon létre egy új hivatkozást a számítógépén.";
@@ -5373,6 +5373,9 @@ report reason */
/* swipe action */
"Unread" = "Olvasatlan";
/* No comment provided by engineer. */
"Unsupported connection link" = "Nem támogatott kapcsolattartási hivatkozás";
/* No comment provided by engineer. */
"Up to 100 last messages are sent to new members." = "Legfeljebb az utolsó 100 üzenet lesz elküldve az új tagok számára.";
@@ -5466,6 +5469,9 @@ report reason */
/* No comment provided by engineer. */
"Use servers" = "Kiszolgálók használata";
/* No comment provided by engineer. */
"Use short links (BETA)" = "Rövid hivatkozások használata (béta)";
/* No comment provided by engineer. */
"Use SimpleX Chat servers?" = "SimpleX Chat-kiszolgálók használata?";
@@ -5475,6 +5481,9 @@ report reason */
/* No comment provided by engineer. */
"Use TCP port %@ when no port is specified." = "A következő TCP-port használata, amikor nincs port megadva: %@.";
/* No comment provided by engineer. */
"Use TCP port 443 for preset servers only." = "A 443-as TCP-port használata kizárólag az előre beállított kiszolgálokhoz.";
/* No comment provided by engineer. */
"Use the app while in the call." = "Használja az alkalmazást hívás közben.";
@@ -5536,7 +5545,7 @@ report reason */
"via relay" = "egy továbbítókiszolgálón keresztül";
/* No comment provided by engineer. */
"Via secure quantum resistant protocol." = "Biztonságos kvantumálló-protokollon keresztül.";
"Via secure quantum resistant protocol." = "Biztonságos kvantumbiztos protokollon keresztül.";
/* No comment provided by engineer. */
"video" = "videó";
@@ -5694,9 +5703,6 @@ report reason */
/* pref value */
"yes" = "igen";
/* No comment provided by engineer. */
"Yes" = "Igen";
/* No comment provided by engineer. */
"you" = "Ön";
+22 -16
View File
@@ -505,6 +505,9 @@ swipe action */
/* No comment provided by engineer. */
"All reports will be archived for you." = "Tutte le segnalazioni verranno archiviate per te.";
/* No comment provided by engineer. */
"All servers" = "Tutti i server";
/* No comment provided by engineer. */
"All your contacts will remain connected." = "Tutti i tuoi contatti resteranno connessi.";
@@ -688,9 +691,6 @@ swipe action */
/* No comment provided by engineer. */
"Archiving database" = "Archiviazione del database";
/* No comment provided by engineer. */
"Ask" = "Chiedi";
/* No comment provided by engineer. */
"Attach" = "Allega";
@@ -3677,7 +3677,7 @@ time to disappear */
/* No comment provided by engineer. */
"Only your contact can send voice messages." = "Solo il tuo contatto può inviare messaggi vocali.";
/* No comment provided by engineer. */
/* alert action */
"Open" = "Apri";
/* No comment provided by engineer. */
@@ -3695,21 +3695,12 @@ time to disappear */
/* No comment provided by engineer. */
"Open group" = "Apri gruppo";
/* No comment provided by engineer. */
"Open link" = "Apri link";
/* No comment provided by engineer. */
"Open links from chat list" = "Apri i link dall'elenco delle chat";
/* authentication reason */
"Open migration to another device" = "Apri migrazione ad un altro dispositivo";
/* No comment provided by engineer. */
"Open Settings" = "Apri le impostazioni";
/* No comment provided by engineer. */
"Open web link?" = "Aprire il link?";
/* No comment provided by engineer. */
"Opening app…" = "Apertura dell'app…";
@@ -4751,6 +4742,9 @@ chat item action */
/* No comment provided by engineer. */
"Share with contacts" = "Condividi con i contatti";
/* No comment provided by engineer. */
"Short link" = "Link breve";
/* No comment provided by engineer. */
"Show → on messages sent via private routing." = "Mostra → nei messaggi inviati via instradamento privato.";
@@ -4793,6 +4787,9 @@ chat item action */
/* No comment provided by engineer. */
"SimpleX address or 1-time link?" = "Indirizzo SimpleX o link una tantum?";
/* simplex link type */
"SimpleX channel link" = "Link del canale SimpleX";
/* No comment provided by engineer. */
"SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app." = "SimpleX Chat e Flux hanno concluso un accordo per includere server gestiti da Flux nell'app.";
@@ -5181,6 +5178,9 @@ report reason */
/* No comment provided by engineer. */
"This is your own SimpleX address!" = "Questo è il tuo indirizzo SimpleX!";
/* No comment provided by engineer. */
"This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link." = "Questo link richiede una versione più recente dell'app. Aggiornala o chiedi al tuo contatto di inviare un link compatibile.";
/* No comment provided by engineer. */
"This link was used with another mobile device, please create a new link on the desktop." = "Questo link è stato usato con un altro dispositivo mobile, creane uno nuovo sul desktop.";
@@ -5373,6 +5373,9 @@ report reason */
/* swipe action */
"Unread" = "Non letto";
/* No comment provided by engineer. */
"Unsupported connection link" = "Link di connessione non supportato";
/* No comment provided by engineer. */
"Up to 100 last messages are sent to new members." = "Vengono inviati ai nuovi membri fino a 100 ultimi messaggi.";
@@ -5466,6 +5469,9 @@ report reason */
/* No comment provided by engineer. */
"Use servers" = "Usa i server";
/* No comment provided by engineer. */
"Use short links (BETA)" = "Usa link brevi (BETA)";
/* No comment provided by engineer. */
"Use SimpleX Chat servers?" = "Usare i server di SimpleX Chat?";
@@ -5475,6 +5481,9 @@ report reason */
/* No comment provided by engineer. */
"Use TCP port %@ when no port is specified." = "Usa la porta TCP %@ quando non è specificata alcuna porta.";
/* No comment provided by engineer. */
"Use TCP port 443 for preset servers only." = "Usa la porta TCP 443 solo per i server preimpostati.";
/* No comment provided by engineer. */
"Use the app while in the call." = "Usa l'app mentre sei in chiamata.";
@@ -5694,9 +5703,6 @@ report reason */
/* pref value */
"yes" = "sì";
/* No comment provided by engineer. */
"Yes" = "Sì";
/* No comment provided by engineer. */
"you" = "tu";
+1 -1
View File
@@ -2367,7 +2367,7 @@ time to disappear */
/* No comment provided by engineer. */
"Only your contact can send voice messages." = "音声メッセージを送れるのはあなたの連絡相手だけです。";
/* No comment provided by engineer. */
/* alert action */
"Open" = "開く";
/* No comment provided by engineer. */
+1 -16
View File
@@ -688,9 +688,6 @@ swipe action */
/* No comment provided by engineer. */
"Archiving database" = "Database archiveren";
/* No comment provided by engineer. */
"Ask" = "Vragen";
/* No comment provided by engineer. */
"Attach" = "Bijvoegen";
@@ -3677,7 +3674,7 @@ time to disappear */
/* No comment provided by engineer. */
"Only your contact can send voice messages." = "Alleen uw contact kan spraak berichten verzenden.";
/* No comment provided by engineer. */
/* alert action */
"Open" = "Open";
/* No comment provided by engineer. */
@@ -3695,21 +3692,12 @@ time to disappear */
/* No comment provided by engineer. */
"Open group" = "Open groep";
/* No comment provided by engineer. */
"Open link" = "Link openen";
/* No comment provided by engineer. */
"Open links from chat list" = "Open links van chatlijst";
/* authentication reason */
"Open migration to another device" = "Open de migratie naar een ander apparaat";
/* No comment provided by engineer. */
"Open Settings" = "Open instellingen";
/* No comment provided by engineer. */
"Open web link?" = "Weblink openen?";
/* No comment provided by engineer. */
"Opening app…" = "App openen…";
@@ -5694,9 +5682,6 @@ report reason */
/* pref value */
"yes" = "Ja";
/* No comment provided by engineer. */
"Yes" = "Ja";
/* No comment provided by engineer. */
"you" = "jij";
+1 -4
View File
@@ -682,9 +682,6 @@ swipe action */
/* No comment provided by engineer. */
"Archiving database" = "Archiwizowanie bazy danych";
/* No comment provided by engineer. */
"Ask" = "Zapytaj";
/* No comment provided by engineer. */
"Attach" = "Dołącz";
@@ -3320,7 +3317,7 @@ time to disappear */
/* No comment provided by engineer. */
"Only your contact can send voice messages." = "Tylko Twój kontakt może wysyłać wiadomości głosowe.";
/* No comment provided by engineer. */
/* alert action */
"Open" = "Otwórz";
/* No comment provided by engineer. */
+1 -16
View File
@@ -685,9 +685,6 @@ swipe action */
/* No comment provided by engineer. */
"Archiving database" = "Подготовка архива";
/* No comment provided by engineer. */
"Ask" = "Спросить";
/* No comment provided by engineer. */
"Attach" = "Прикрепить";
@@ -3575,7 +3572,7 @@ time to disappear */
/* No comment provided by engineer. */
"Only your contact can send voice messages." = "Только Ваш контакт может отправлять голосовые сообщения.";
/* No comment provided by engineer. */
/* alert action */
"Open" = "Открыть";
/* No comment provided by engineer. */
@@ -3593,21 +3590,12 @@ time to disappear */
/* No comment provided by engineer. */
"Open group" = "Открыть группу";
/* No comment provided by engineer. */
"Open link" = "Открыть ссылку";
/* No comment provided by engineer. */
"Open links from chat list" = "Открыть ссылку из списка чатов";
/* authentication reason */
"Open migration to another device" = "Открытие миграции на другое устройство";
/* No comment provided by engineer. */
"Open Settings" = "Открыть Настройки";
/* No comment provided by engineer. */
"Open web link?" = "Открыть веб-ссылку?";
/* No comment provided by engineer. */
"Opening app…" = "Приложение отрывается…";
@@ -5544,9 +5532,6 @@ report reason */
/* pref value */
"yes" = "да";
/* No comment provided by engineer. */
"Yes" = "Да";
/* No comment provided by engineer. */
"you" = "Вы";
+1 -1
View File
@@ -3353,7 +3353,7 @@ time to disappear */
/* No comment provided by engineer. */
"Only your contact can send voice messages." = "Sadece karşıdaki kişi sesli mesajlar gönderebilir.";
/* No comment provided by engineer. */
/* alert action */
"Open" = "Aç";
/* No comment provided by engineer. */
+1 -1
View File
@@ -3401,7 +3401,7 @@ time to disappear */
/* No comment provided by engineer. */
"Only your contact can send voice messages." = "Тільки ваш контакт може надсилати голосові повідомлення.";
/* No comment provided by engineer. */
/* alert action */
"Open" = "Відкрито";
/* No comment provided by engineer. */
File diff suppressed because it is too large Load Diff
@@ -3902,7 +3902,7 @@ enum class MsgContentTag {
class FormattedText(val text: String, val format: Format? = null) {
// TODO make it dependent on simplexLinkMode preference
fun link(mode: SimplexLinkMode): String? = when (format) {
is Format.Uri -> text
is Format.Uri -> if (text.startsWith("http://", ignoreCase = true) || text.startsWith("https://", ignoreCase = true)) text else "https://$text"
is Format.SimplexLink -> if (mode == SimplexLinkMode.BROWSER) text else format.simplexUri
is Format.Email -> "mailto:$text"
is Format.Phone -> "tel:$text"

Some files were not shown because too many files have changed in this diff Show More