mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2024-12-17 17:20:21 +01:00
Compare commits
109 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e67feeea22 | |||
| da65474452 | |||
| d0a7e14a96 | |||
| bd4745775d | |||
| af144c6208 | |||
| 74206a947b | |||
| 457e12880c | |||
| 2d588949b1 | |||
| 84f7f901ea | |||
| 90ed503ee0 | |||
| 28105038d4 | |||
| fd60a2402a | |||
| ef0f21a11c | |||
| d0e40c1f1d | |||
| 8396e70e7b | |||
| 6128a24869 | |||
| 0329a6a7d3 | |||
| 2da89c2cf1 | |||
| 601ddf97ce | |||
| 128d031ced | |||
| 3b0205b25f | |||
| d4a47f1cce | |||
| 2998e3af3f | |||
| 5ff838d63e | |||
| bdaec30fa0 | |||
| 5a8bf9106e | |||
| 97df069730 | |||
| 9a1166f097 | |||
| 7a741e7ac4 | |||
| 165143a111 | |||
| ceb17b23b4 | |||
| 3c8c9d8b52 | |||
| 4162bccc46 | |||
| 24090fe350 | |||
| 37b78edb91 | |||
| 78510b6fd3 | |||
| edf99fcd1d | |||
| 2ffabd1ef8 | |||
| 28383edb83 | |||
| 9175897acf | |||
| f3cd167502 | |||
| 7cde2cf6c2 | |||
| 3913043705 | |||
| a160acef12 | |||
| c54fae0136 | |||
| d57abfcc93 | |||
| 515a0ddfdd | |||
| b5d8c65249 | |||
| de94892fe7 | |||
| b7131e16f2 | |||
| 11a44dc1fd | |||
| 0af718f03f | |||
| f8f5c3c6be | |||
| 13912a4af9 | |||
| 601b4cd619 | |||
| d2b4b7bed6 | |||
| fa95e4e9ad | |||
| 88fdc1ef75 | |||
| 7ab6e44a6e | |||
| 26986686ca | |||
| e76dc33cf0 | |||
| aa2eafdacb | |||
| 2c3c97f5cc | |||
| 83f42704ea | |||
| 7ff6ef09fe | |||
| dbe4504f05 | |||
| 9a87f344b5 | |||
| 2127c7dcce | |||
| e3528d3ffe | |||
| ec014d721e | |||
| 75bacb7923 | |||
| 0d8c179861 | |||
| e9a99dfb3c | |||
| baa585357f | |||
| cebb4aa93b | |||
| df53ae9d4f | |||
| 21b1904b0e | |||
| b1ef442f1e | |||
| 4020cb074f | |||
| 0c69f6553a | |||
| 03865b4a18 | |||
| ac5f0bc7bb | |||
| 12423f4afa | |||
| fabbe0285d | |||
| b01efd9d0a | |||
| fc28ff0f15 | |||
| 213f6cf372 | |||
| a764e1906d | |||
| 54b40a5838 | |||
| 35fc0544a0 | |||
| 6907f02ea6 | |||
| c6ece8afdd | |||
| a00e5901de | |||
| ad2a0024f2 | |||
| c5261a416f | |||
| 193e17f7af | |||
| 87fd642951 | |||
| fb044000d2 | |||
| 69791dbdcf | |||
| dc11202250 | |||
| 96ac0a7715 | |||
| bdb6bd6e20 | |||
| 7ccd80bf23 | |||
| f0d6f15393 | |||
| 49c91283d8 | |||
| 55de5b9ce9 | |||
| 8727d3b91b | |||
| bb2a6ec65d | |||
| 6118fca000 |
+1
-1
@@ -29,7 +29,7 @@ RUN cp ./scripts/cabal.project.local.linux ./cabal.project.local
|
|||||||
|
|
||||||
# Compile simplex-chat
|
# Compile simplex-chat
|
||||||
RUN cabal update
|
RUN cabal update
|
||||||
RUN cabal build exe:simplex-chat
|
RUN cabal build exe:simplex-chat --constraint 'simplexmq +client_library'
|
||||||
|
|
||||||
# Strip the binary from debug symbols to reduce size
|
# Strip the binary from debug symbols to reduce size
|
||||||
RUN bin=$(find /project/dist-newstyle -name "simplex-chat" -type f -executable) && \
|
RUN bin=$(find /project/dist-newstyle -name "simplex-chat" -type f -executable) && \
|
||||||
|
|||||||
+4
-2
@@ -25,7 +25,9 @@ While SimpleX Chat Ltd is not a communication service provider, and provide publ
|
|||||||
|
|
||||||
We see users and data sovereignty, and device and provider portability as critically important properties for any communication system.
|
We see users and data sovereignty, and device and provider portability as critically important properties for any communication system.
|
||||||
|
|
||||||
SimpleX Chat security assessment was done in October 2022 by [Trail of Bits](https://www.trailofbits.com/about), and most fixes were released in v4.2 – see [the announcement](/blog/20221108-simplex-chat-v4.2-security-audit-new-website.md).
|
The implementation security assessment of SimpleX cryptography and networking was done in October 2022 by [Trail of Bits](https://www.trailofbits.com/about), and most fixes were released in v4.2 – see [the announcement](/blog/20221108-simplex-chat-v4.2-security-audit-new-website.md).
|
||||||
|
|
||||||
|
The cryptographic review of SimpleX protocols design was done in July 2024 by Trail of Bits – see [the announcement](/blog/20241014-simplex-network-v6-1-security-review-better-calls-user-experience.md).
|
||||||
|
|
||||||
### Your information
|
### Your information
|
||||||
|
|
||||||
@@ -172,4 +174,4 @@ You accept the Conditions of Use of Software and Infrastructure ("Conditions") b
|
|||||||
|
|
||||||
**Ending these conditions**. You may end these Conditions with SimpleX Chat Ltd at any time by deleting our Applications from your devices and discontinuing use of our Infrastructure. The provisions related to Licenses, Disclaimers, Limitation of Liability, Resolving dispute, Availability, Changes to the conditions, Enforcing the conditions, and Ending these conditions will survive termination of your relationship with SimpleX Chat Ltd.
|
**Ending these conditions**. You may end these Conditions with SimpleX Chat Ltd at any time by deleting our Applications from your devices and discontinuing use of our Infrastructure. The provisions related to Licenses, Disclaimers, Limitation of Liability, Resolving dispute, Availability, Changes to the conditions, Enforcing the conditions, and Ending these conditions will survive termination of your relationship with SimpleX Chat Ltd.
|
||||||
|
|
||||||
Updated April 24, 2024
|
Updated October 14, 2024
|
||||||
|
|||||||
@@ -233,14 +233,12 @@ You can use SimpleX with your own servers and still communicate with people usin
|
|||||||
|
|
||||||
Recent and important updates:
|
Recent and important updates:
|
||||||
|
|
||||||
|
[Oct 14, 2024. SimpleX network: security review of protocols design by Trail of Bits, v6.1 released with better calls and user experience.](./blog/20241014-simplex-network-v6-1-security-review-better-calls-user-experience.md)
|
||||||
|
|
||||||
[Aug 14, 2024. SimpleX network: the investment from Jack Dorsey and Asymmetric, v6.0 released with the new user experience and private message routing](./blog/20240814-simplex-chat-vision-funding-v6-private-routing-new-user-experience.md)
|
[Aug 14, 2024. SimpleX network: the investment from Jack Dorsey and Asymmetric, v6.0 released with the new user experience and private message routing](./blog/20240814-simplex-chat-vision-funding-v6-private-routing-new-user-experience.md)
|
||||||
|
|
||||||
[Jun 4, 2024. SimpleX network: private message routing, v5.8 released with IP address protection and chat themes](./blog/20240604-simplex-chat-v5.8-private-message-routing-chat-themes.md)
|
[Jun 4, 2024. SimpleX network: private message routing, v5.8 released with IP address protection and chat themes](./blog/20240604-simplex-chat-v5.8-private-message-routing-chat-themes.md)
|
||||||
|
|
||||||
[Apr 26, 2024. SimpleX network: legally binding transparency, v5.7 released with better calls and messages.](./blog/20240426-simplex-legally-binding-transparency-v5-7-better-user-experience.md)
|
|
||||||
|
|
||||||
[Mar 23, 2024. SimpleX network: real privacy and stable profits, non-profits for protocols, v5.6 released with quantum resistant e2e encryption and simple profile migration.](./blog/20240323-simplex-network-privacy-non-profit-v5-6-quantum-resistant-e2e-encryption-simple-migration.md)
|
|
||||||
|
|
||||||
[Mar 14, 2024. SimpleX Chat v5.6 beta: adding quantum resistance to Signal double ratchet algorithm.](./blog/20240314-simplex-chat-v5-6-quantum-resistance-signal-double-ratchet-algorithm.md)
|
[Mar 14, 2024. SimpleX Chat v5.6 beta: adding quantum resistance to Signal double ratchet algorithm.](./blog/20240314-simplex-chat-v5-6-quantum-resistance-signal-double-ratchet-algorithm.md)
|
||||||
|
|
||||||
[Jan 24, 2024. SimpleX Chat: free infrastructure from Linode, v5.5 released with private notes, group history and a simpler UX to connect.](./blog/20240124-simplex-chat-infrastructure-costs-v5-5-simplex-ux-private-notes-group-history.md)
|
[Jan 24, 2024. SimpleX Chat: free infrastructure from Linode, v5.5 released with private notes, group history and a simpler UX to connect.](./blog/20240124-simplex-chat-infrastructure-costs-v5-5-simplex-ux-private-notes-group-history.md)
|
||||||
@@ -249,10 +247,6 @@ Recent and important updates:
|
|||||||
|
|
||||||
[Sep 25, 2023. SimpleX Chat v5.3 released: desktop app, local file encryption, improved groups and directory service](./blog/20230925-simplex-chat-v5-3-desktop-app-local-file-encryption-directory-service.md).
|
[Sep 25, 2023. SimpleX Chat v5.3 released: desktop app, local file encryption, improved groups and directory service](./blog/20230925-simplex-chat-v5-3-desktop-app-local-file-encryption-directory-service.md).
|
||||||
|
|
||||||
[Jul 22, 2023. SimpleX Chat: v5.2 released with message delivery receipts](./blog/20230722-simplex-chat-v5-2-message-delivery-receipts.md).
|
|
||||||
|
|
||||||
[May 23, 2023. SimpleX Chat: v5.1 released with message reactions and self-destruct passcode](./blog/20230523-simplex-chat-v5-1-message-reactions-self-destruct-passcode.md).
|
|
||||||
|
|
||||||
[Apr 22, 2023. SimpleX Chat: vision and funding, v5.0 released with videos and files up to 1gb](./blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.md).
|
[Apr 22, 2023. SimpleX Chat: vision and funding, v5.0 released with videos and files up to 1gb](./blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.md).
|
||||||
|
|
||||||
[Mar 1, 2023. SimpleX File Transfer Protocol – send large files efficiently, privately and securely, soon to be integrated into SimpleX Chat apps.](./blog/20230301-simplex-file-transfer-protocol.md).
|
[Mar 1, 2023. SimpleX File Transfer Protocol – send large files efficiently, privately and securely, soon to be integrated into SimpleX Chat apps.](./blog/20230301-simplex-file-transfer-protocol.md).
|
||||||
@@ -409,7 +403,9 @@ Please also join [#simplex-devs](https://simplex.chat/contact#/?v=1-2&smp=smp%3A
|
|||||||
|
|
||||||
[SimpleX protocols and security model](https://github.com/simplex-chat/simplexmq/blob/master/protocol/overview-tjr.md) was reviewed, and had many breaking changes and improvements in v1.0.0.
|
[SimpleX protocols and security model](https://github.com/simplex-chat/simplexmq/blob/master/protocol/overview-tjr.md) was reviewed, and had many breaking changes and improvements in v1.0.0.
|
||||||
|
|
||||||
The security audit was performed in October 2022 by [Trail of Bits](https://www.trailofbits.com/about), and most fixes were released in v4.2.0 – see [the announcement](./blog/20221108-simplex-chat-v4.2-security-audit-new-website.md).
|
The implementation security assessment of SimpleX cryptography and networking was done in October 2022 by [Trail of Bits](https://www.trailofbits.com/about) – see [the announcement](./blog/20221108-simplex-chat-v4.2-security-audit-new-website.md).
|
||||||
|
|
||||||
|
The cryptographic review of SimpleX protocols was done in July 2024 by Trail of Bits – see [the announcement](./blog/20241014-simplex-network-v6-1-security-review-better-calls-user-experience.md).
|
||||||
|
|
||||||
SimpleX Chat is still a relatively early stage platform (the mobile apps were released in March 2022), so you may discover some bugs and missing features. We would really appreciate if you let us know anything that needs to be fixed or improved.
|
SimpleX Chat is still a relatively early stage platform (the mobile apps were released in March 2022), so you may discover some bugs and missing features. We would really appreciate if you let us know anything that needs to be fixed or improved.
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ struct ContentView: View {
|
|||||||
@EnvironmentObject var chatModel: ChatModel
|
@EnvironmentObject var chatModel: ChatModel
|
||||||
@ObservedObject var alertManager = AlertManager.shared
|
@ObservedObject var alertManager = AlertManager.shared
|
||||||
@ObservedObject var callController = CallController.shared
|
@ObservedObject var callController = CallController.shared
|
||||||
|
@ObservedObject var appSheetState = AppSheetState.shared
|
||||||
@Environment(\.colorScheme) var colorScheme
|
@Environment(\.colorScheme) var colorScheme
|
||||||
@EnvironmentObject var theme: AppTheme
|
@EnvironmentObject var theme: AppTheme
|
||||||
@EnvironmentObject var sceneDelegate: SceneDelegate
|
@EnvironmentObject var sceneDelegate: SceneDelegate
|
||||||
@@ -29,12 +30,12 @@ struct ContentView: View {
|
|||||||
@AppStorage(DEFAULT_PERFORM_LA) private var prefPerformLA = false
|
@AppStorage(DEFAULT_PERFORM_LA) private var prefPerformLA = false
|
||||||
@AppStorage(DEFAULT_PRIVACY_PROTECT_SCREEN) private var protectScreen = false
|
@AppStorage(DEFAULT_PRIVACY_PROTECT_SCREEN) private var protectScreen = false
|
||||||
@AppStorage(DEFAULT_NOTIFICATION_ALERT_SHOWN) private var notificationAlertShown = false
|
@AppStorage(DEFAULT_NOTIFICATION_ALERT_SHOWN) private var notificationAlertShown = false
|
||||||
@State private var showSettings = false
|
|
||||||
@State private var showWhatsNew = false
|
@State private var showWhatsNew = false
|
||||||
@State private var showChooseLAMode = false
|
@State private var showChooseLAMode = false
|
||||||
@State private var showSetPasscode = false
|
@State private var showSetPasscode = false
|
||||||
@State private var waitingForOrPassedAuth = true
|
@State private var waitingForOrPassedAuth = true
|
||||||
@State private var chatListActionSheet: ChatListActionSheet? = nil
|
@State private var chatListActionSheet: ChatListActionSheet? = nil
|
||||||
|
@State private var chatListUserPickerSheet: UserPickerSheet? = nil
|
||||||
|
|
||||||
private let callTopPadding: CGFloat = 40
|
private let callTopPadding: CGFloat = 40
|
||||||
|
|
||||||
@@ -86,7 +87,7 @@ struct ContentView: View {
|
|||||||
callView(call)
|
callView(call)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !showSettings, let la = chatModel.laRequest {
|
if chatListUserPickerSheet == nil, let la = chatModel.laRequest {
|
||||||
LocalAuthView(authRequest: la)
|
LocalAuthView(authRequest: la)
|
||||||
.onDisappear {
|
.onDisappear {
|
||||||
// this flag is separate from accessAuthenticated to show initializationView while we wait for authentication
|
// this flag is separate from accessAuthenticated to show initializationView while we wait for authentication
|
||||||
@@ -109,9 +110,6 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.alert(isPresented: $alertManager.presentAlert) { alertManager.alertView! }
|
.alert(isPresented: $alertManager.presentAlert) { alertManager.alertView! }
|
||||||
.sheet(isPresented: $showSettings) {
|
|
||||||
SettingsView(showSettings: $showSettings)
|
|
||||||
}
|
|
||||||
.confirmationDialog("SimpleX Lock mode", isPresented: $showChooseLAMode, titleVisibility: .visible) {
|
.confirmationDialog("SimpleX Lock mode", isPresented: $showChooseLAMode, titleVisibility: .visible) {
|
||||||
Button("System authentication") { initialEnableLA() }
|
Button("System authentication") { initialEnableLA() }
|
||||||
Button("Passcode entry") { showSetPasscode = true }
|
Button("Passcode entry") { showSetPasscode = true }
|
||||||
@@ -253,7 +251,8 @@ struct ContentView: View {
|
|||||||
|
|
||||||
private func mainView() -> some View {
|
private func mainView() -> some View {
|
||||||
ZStack(alignment: .top) {
|
ZStack(alignment: .top) {
|
||||||
ChatListView(showSettings: $showSettings).privacySensitive(protectScreen)
|
ChatListView(activeUserPickerSheet: $chatListUserPickerSheet)
|
||||||
|
.redacted(reason: appSheetState.redactionReasons(protectScreen))
|
||||||
.onAppear {
|
.onAppear {
|
||||||
requestNtfAuthorization()
|
requestNtfAuthorization()
|
||||||
// Local Authentication notice is to be shown on next start after onboarding is complete
|
// Local Authentication notice is to be shown on next start after onboarding is complete
|
||||||
@@ -300,9 +299,18 @@ struct ContentView: View {
|
|||||||
if let contactId = contacts?.first?.personHandle?.value,
|
if let contactId = contacts?.first?.personHandle?.value,
|
||||||
let chat = chatModel.getChat(contactId),
|
let chat = chatModel.getChat(contactId),
|
||||||
case let .direct(contact) = chat.chatInfo {
|
case let .direct(contact) = chat.chatInfo {
|
||||||
logger.debug("callToRecentContact: schedule call")
|
let activeCall = chatModel.activeCall
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
// This line works when a user clicks on a video button in CallKit UI while in call.
|
||||||
CallController.shared.startCall(contact, mediaType)
|
// The app tries to make another call to the same contact and overwite activeCall instance making its state broken
|
||||||
|
if let activeCall, contactId == activeCall.contact.id, mediaType == .video, !activeCall.hasVideo {
|
||||||
|
Task {
|
||||||
|
await chatModel.callCommand.processCommand(.media(source: .camera, enable: true))
|
||||||
|
}
|
||||||
|
} else if activeCall == nil {
|
||||||
|
logger.debug("callToRecentContact: schedule call")
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||||
|
CallController.shared.startCall(contact, mediaType)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,6 +147,7 @@ final class ChatModel: ObservableObject {
|
|||||||
@Published var chatDbEncrypted: Bool?
|
@Published var chatDbEncrypted: Bool?
|
||||||
@Published var chatDbStatus: DBMigrationResult?
|
@Published var chatDbStatus: DBMigrationResult?
|
||||||
@Published var ctrlInitInProgress: Bool = false
|
@Published var ctrlInitInProgress: Bool = false
|
||||||
|
@Published var notificationResponse: UNNotificationResponse?
|
||||||
// local authentication
|
// local authentication
|
||||||
@Published var contentViewAccessAuthenticated: Bool = false
|
@Published var contentViewAccessAuthenticated: Bool = false
|
||||||
@Published var laRequest: LocalAuthRequest?
|
@Published var laRequest: LocalAuthRequest?
|
||||||
@@ -526,7 +527,7 @@ final class ChatModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateCurrentUserUiThemes(uiThemes: ThemeModeOverrides?) {
|
func updateCurrentUserUiThemes(uiThemes: ThemeModeOverrides?) {
|
||||||
guard var current = currentUser else { return }
|
guard var current = currentUser, current.uiThemes != uiThemes else { return }
|
||||||
current.uiThemes = uiThemes
|
current.uiThemes = uiThemes
|
||||||
let i = users.firstIndex(where: { $0.user.userId == current.userId })
|
let i = users.firstIndex(where: { $0.user.userId == current.userId })
|
||||||
if let i {
|
if let i {
|
||||||
|
|||||||
@@ -29,17 +29,33 @@ class NtfManager: NSObject, UNUserNotificationCenterDelegate, ObservableObject {
|
|||||||
private var granted = false
|
private var granted = false
|
||||||
private var prevNtfTime: Dictionary<ChatId, Date> = [:]
|
private var prevNtfTime: Dictionary<ChatId, Date> = [:]
|
||||||
|
|
||||||
|
override init() {
|
||||||
|
super.init()
|
||||||
|
UNUserNotificationCenter.current().delegate = self
|
||||||
|
}
|
||||||
|
|
||||||
// Handle notification when app is in background
|
// Handle notification when app is in background
|
||||||
func userNotificationCenter(_ center: UNUserNotificationCenter,
|
func userNotificationCenter(_ center: UNUserNotificationCenter,
|
||||||
didReceive response: UNNotificationResponse,
|
didReceive response: UNNotificationResponse,
|
||||||
withCompletionHandler handler: () -> Void) {
|
withCompletionHandler handler: () -> Void) {
|
||||||
logger.debug("NtfManager.userNotificationCenter: didReceive")
|
logger.debug("NtfManager.userNotificationCenter: didReceive")
|
||||||
let content = response.notification.request.content
|
if appStateGroupDefault.get() == .active {
|
||||||
|
processNotificationResponse(response)
|
||||||
|
} else {
|
||||||
|
logger.debug("NtfManager.userNotificationCenter: remember response in model")
|
||||||
|
ChatModel.shared.notificationResponse = response
|
||||||
|
}
|
||||||
|
handler()
|
||||||
|
}
|
||||||
|
|
||||||
|
func processNotificationResponse(_ ntfResponse: UNNotificationResponse) {
|
||||||
let chatModel = ChatModel.shared
|
let chatModel = ChatModel.shared
|
||||||
let action = response.actionIdentifier
|
let content = ntfResponse.notification.request.content
|
||||||
logger.debug("NtfManager.userNotificationCenter: didReceive: action \(action), categoryIdentifier \(content.categoryIdentifier)")
|
let action = ntfResponse.actionIdentifier
|
||||||
|
logger.debug("NtfManager.processNotificationResponse: didReceive: action \(action), categoryIdentifier \(content.categoryIdentifier)")
|
||||||
if let userId = content.userInfo["userId"] as? Int64,
|
if let userId = content.userInfo["userId"] as? Int64,
|
||||||
userId != chatModel.currentUser?.userId {
|
userId != chatModel.currentUser?.userId {
|
||||||
|
logger.debug("NtfManager.processNotificationResponse changeActiveUser")
|
||||||
changeActiveUser(userId, viewPwd: nil)
|
changeActiveUser(userId, viewPwd: nil)
|
||||||
}
|
}
|
||||||
if content.categoryIdentifier == ntfCategoryContactRequest && (action == ntfActionAcceptContact || action == ntfActionAcceptContactIncognito),
|
if content.categoryIdentifier == ntfCategoryContactRequest && (action == ntfActionAcceptContact || action == ntfActionAcceptContactIncognito),
|
||||||
@@ -61,7 +77,6 @@ class NtfManager: NSObject, UNUserNotificationCenterDelegate, ObservableObject {
|
|||||||
ItemsModel.shared.loadOpenChat(chatId)
|
ItemsModel.shared.loadOpenChat(chatId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handler()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func ntfCallAction(_ content: UNNotificationContent, _ action: String) -> (ChatId, NtfCallAction)? {
|
private func ntfCallAction(_ content: UNNotificationContent, _ action: String) -> (ChatId, NtfCallAction)? {
|
||||||
@@ -76,7 +91,6 @@ class NtfManager: NSObject, UNUserNotificationCenterDelegate, ObservableObject {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Handle notification when the app is in foreground
|
// Handle notification when the app is in foreground
|
||||||
func userNotificationCenter(_ center: UNUserNotificationCenter,
|
func userNotificationCenter(_ center: UNUserNotificationCenter,
|
||||||
willPresent notification: UNNotification,
|
willPresent notification: UNNotification,
|
||||||
@@ -185,6 +199,12 @@ class NtfManager: NSObject, UNUserNotificationCenterDelegate, ObservableObject {
|
|||||||
actions: [],
|
actions: [],
|
||||||
intentIdentifiers: [],
|
intentIdentifiers: [],
|
||||||
hiddenPreviewsBodyPlaceholder: NSLocalizedString("SimpleX encrypted message or connection event", comment: "notification")
|
hiddenPreviewsBodyPlaceholder: NSLocalizedString("SimpleX encrypted message or connection event", comment: "notification")
|
||||||
|
),
|
||||||
|
UNNotificationCategory(
|
||||||
|
identifier: ntfCategoryManyEvents,
|
||||||
|
actions: [],
|
||||||
|
intentIdentifiers: [],
|
||||||
|
hiddenPreviewsBodyPlaceholder: NSLocalizedString("New events", comment: "notification")
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
@@ -210,29 +230,28 @@ class NtfManager: NSObject, UNUserNotificationCenterDelegate, ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
center.delegate = self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func notifyContactRequest(_ user: any UserLike, _ contactRequest: UserContactRequest) {
|
func notifyContactRequest(_ user: any UserLike, _ contactRequest: UserContactRequest) {
|
||||||
logger.debug("NtfManager.notifyContactRequest")
|
logger.debug("NtfManager.notifyContactRequest")
|
||||||
addNotification(createContactRequestNtf(user, contactRequest))
|
addNotification(createContactRequestNtf(user, contactRequest, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
func notifyContactConnected(_ user: any UserLike, _ contact: Contact) {
|
func notifyContactConnected(_ user: any UserLike, _ contact: Contact) {
|
||||||
logger.debug("NtfManager.notifyContactConnected")
|
logger.debug("NtfManager.notifyContactConnected")
|
||||||
addNotification(createContactConnectedNtf(user, contact))
|
addNotification(createContactConnectedNtf(user, contact, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
func notifyMessageReceived(_ user: any UserLike, _ cInfo: ChatInfo, _ cItem: ChatItem) {
|
func notifyMessageReceived(_ user: any UserLike, _ cInfo: ChatInfo, _ cItem: ChatItem) {
|
||||||
logger.debug("NtfManager.notifyMessageReceived")
|
logger.debug("NtfManager.notifyMessageReceived")
|
||||||
if cInfo.ntfsEnabled {
|
if cInfo.ntfsEnabled {
|
||||||
addNotification(createMessageReceivedNtf(user, cInfo, cItem))
|
addNotification(createMessageReceivedNtf(user, cInfo, cItem, 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func notifyCallInvitation(_ invitation: RcvCallInvitation) {
|
func notifyCallInvitation(_ invitation: RcvCallInvitation) {
|
||||||
logger.debug("NtfManager.notifyCallInvitation")
|
logger.debug("NtfManager.notifyCallInvitation")
|
||||||
addNotification(createCallInvitationNtf(invitation))
|
addNotification(createCallInvitationNtf(invitation, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
func setNtfBadgeCount(_ count: Int) {
|
func setNtfBadgeCount(_ count: Int) {
|
||||||
|
|||||||
@@ -462,7 +462,7 @@ func apiGetNtfToken() -> (DeviceToken?, NtfTknStatus?, NotificationsMode, String
|
|||||||
let r = chatSendCmdSync(.apiGetNtfToken)
|
let r = chatSendCmdSync(.apiGetNtfToken)
|
||||||
switch r {
|
switch r {
|
||||||
case let .ntfToken(token, status, ntfMode, ntfServer): return (token, status, ntfMode, ntfServer)
|
case let .ntfToken(token, status, ntfMode, ntfServer): return (token, status, ntfMode, ntfServer)
|
||||||
case .chatCmdError(_, .errorAgent(.CMD(.PROHIBITED))): return (nil, nil, .off, nil)
|
case .chatCmdError(_, .errorAgent(.CMD(.PROHIBITED, _))): return (nil, nil, .off, nil)
|
||||||
default:
|
default:
|
||||||
logger.debug("apiGetNtfToken response: \(String(describing: r))")
|
logger.debug("apiGetNtfToken response: \(String(describing: r))")
|
||||||
return (nil, nil, .off, nil)
|
return (nil, nil, .off, nil)
|
||||||
@@ -585,12 +585,18 @@ func apiContactInfo(_ contactId: Int64) async throws -> (ConnectionStats?, Profi
|
|||||||
throw r
|
throw r
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiGroupMemberInfo(_ groupId: Int64, _ groupMemberId: Int64) throws -> (GroupMember, ConnectionStats?) {
|
func apiGroupMemberInfoSync(_ groupId: Int64, _ groupMemberId: Int64) throws -> (GroupMember, ConnectionStats?) {
|
||||||
let r = chatSendCmdSync(.apiGroupMemberInfo(groupId: groupId, groupMemberId: groupMemberId))
|
let r = chatSendCmdSync(.apiGroupMemberInfo(groupId: groupId, groupMemberId: groupMemberId))
|
||||||
if case let .groupMemberInfo(_, _, member, connStats_) = r { return (member, connStats_) }
|
if case let .groupMemberInfo(_, _, member, connStats_) = r { return (member, connStats_) }
|
||||||
throw r
|
throw r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func apiGroupMemberInfo(_ groupId: Int64, _ groupMemberId: Int64) async throws -> (GroupMember, ConnectionStats?) {
|
||||||
|
let r = await chatSendCmd(.apiGroupMemberInfo(groupId: groupId, groupMemberId: groupMemberId))
|
||||||
|
if case let .groupMemberInfo(_, _, member, connStats_) = r { return (member, connStats_) }
|
||||||
|
throw r
|
||||||
|
}
|
||||||
|
|
||||||
func apiContactQueueInfo(_ contactId: Int64) async throws -> (RcvMsgInfo?, ServerQueueInfo) {
|
func apiContactQueueInfo(_ contactId: Int64) async throws -> (RcvMsgInfo?, ServerQueueInfo) {
|
||||||
let r = await chatSendCmd(.apiContactQueueInfo(contactId: contactId))
|
let r = await chatSendCmd(.apiContactQueueInfo(contactId: contactId))
|
||||||
if case let .queueInfo(_, rcvMsgInfo, queueInfo) = r { return (rcvMsgInfo, queueInfo) }
|
if case let .queueInfo(_, rcvMsgInfo, queueInfo) = r { return (rcvMsgInfo, queueInfo) }
|
||||||
@@ -645,8 +651,8 @@ func apiGetContactCode(_ contactId: Int64) async throws -> (Contact, String) {
|
|||||||
throw r
|
throw r
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiGetGroupMemberCode(_ groupId: Int64, _ groupMemberId: Int64) throws -> (GroupMember, String) {
|
func apiGetGroupMemberCode(_ groupId: Int64, _ groupMemberId: Int64) async throws -> (GroupMember, String) {
|
||||||
let r = chatSendCmdSync(.apiGetGroupMemberCode(groupId: groupId, groupMemberId: groupMemberId))
|
let r = await chatSendCmd(.apiGetGroupMemberCode(groupId: groupId, groupMemberId: groupMemberId))
|
||||||
if case let .groupMemberCode(_, _, member, connectionCode) = r { return (member, connectionCode) }
|
if case let .groupMemberCode(_, _, member, connectionCode) = r { return (member, connectionCode) }
|
||||||
throw r
|
throw r
|
||||||
}
|
}
|
||||||
@@ -737,6 +743,12 @@ func apiConnect_(incognito: Bool, connReq: String) async -> ((ConnReqType, Pendi
|
|||||||
message: "Unless your contact deleted the connection or this link was already used, it might be a bug - please report it.\nTo connect, please ask your contact to create another connection link and check that you have a stable network connection."
|
message: "Unless your contact deleted the connection or this link was already used, it might be a bug - please report it.\nTo connect, please ask your contact to create another connection link and check that you have a stable network connection."
|
||||||
)
|
)
|
||||||
return (nil, alert)
|
return (nil, alert)
|
||||||
|
case .chatCmdError(_, .errorAgent(.SMP(_, .QUOTA))):
|
||||||
|
let alert = mkAlert(
|
||||||
|
title: "Undelivered messages",
|
||||||
|
message: "The connection reached the limit of undelivered messages, your contact may be offline."
|
||||||
|
)
|
||||||
|
return (nil, alert)
|
||||||
case let .chatCmdError(_, .errorAgent(.INTERNAL(internalErr))):
|
case let .chatCmdError(_, .errorAgent(.INTERNAL(internalErr))):
|
||||||
if internalErr == "SEUniqueID" {
|
if internalErr == "SEUniqueID" {
|
||||||
let alert = mkAlert(
|
let alert = mkAlert(
|
||||||
@@ -2084,7 +2096,6 @@ func processReceivedMsg(_ res: ChatResponse) async {
|
|||||||
await withCall(contact) { call in
|
await withCall(contact) { call in
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
call.callState = .offerReceived
|
call.callState = .offerReceived
|
||||||
call.peerMedia = callType.media
|
|
||||||
call.sharedKey = sharedKey
|
call.sharedKey = sharedKey
|
||||||
}
|
}
|
||||||
let useRelay = UserDefaults.standard.bool(forKey: DEFAULT_WEBRTC_POLICY_RELAY)
|
let useRelay = UserDefaults.standard.bool(forKey: DEFAULT_WEBRTC_POLICY_RELAY)
|
||||||
|
|||||||
@@ -82,11 +82,17 @@ struct SimpleXApp: App {
|
|||||||
|
|
||||||
if appState != .stopped {
|
if appState != .stopped {
|
||||||
startChatAndActivate {
|
startChatAndActivate {
|
||||||
if appState.inactive && chatModel.chatRunning == true {
|
if chatModel.chatRunning == true {
|
||||||
Task {
|
if let ntfResponse = chatModel.notificationResponse {
|
||||||
await updateChats()
|
chatModel.notificationResponse = nil
|
||||||
if !chatModel.showCallView && !CallController.shared.hasActiveCalls() {
|
NtfManager.shared.processNotificationResponse(ntfResponse)
|
||||||
await updateCallInvitations()
|
}
|
||||||
|
if appState.inactive {
|
||||||
|
Task {
|
||||||
|
await updateChats()
|
||||||
|
if !chatModel.showCallView && !CallController.shared.hasActiveCalls() {
|
||||||
|
await updateCallInvitations()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ extension ThemeWallpaper {
|
|||||||
let preset: String? = if case let WallpaperType.preset(filename, _) = type { filename } else { nil }
|
let preset: String? = if case let WallpaperType.preset(filename, _) = type { filename } else { nil }
|
||||||
let scale: Float? = if case let WallpaperType.preset(_, scale) = type { scale } else { if case let WallpaperType.image(_, scale, _) = type { scale } else { 1.0 } }
|
let scale: Float? = if case let WallpaperType.preset(_, scale) = type { scale } else { if case let WallpaperType.image(_, scale, _) = type { scale } else { 1.0 } }
|
||||||
let scaleType: WallpaperScaleType? = if case let WallpaperType.image(_, _, scaleType) = type { scaleType } else { nil }
|
let scaleType: WallpaperScaleType? = if case let WallpaperType.image(_, _, scaleType) = type { scaleType } else { nil }
|
||||||
let image: String? = if case WallpaperType.image = type, let image = type.uiImage { resizeImageToStrSize(image, maxDataSize: 5_000_000) } else { nil }
|
let image: String? = if case WallpaperType.image = type, let image = type.uiImage { resizeImageToStrSizeSync(image, maxDataSize: 5_000_000) } else { nil }
|
||||||
return ThemeWallpaper (
|
return ThemeWallpaper (
|
||||||
preset: preset,
|
preset: preset,
|
||||||
scale: scale,
|
scale: scale,
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ struct ActiveCallView: View {
|
|||||||
@ObservedObject var call: Call
|
@ObservedObject var call: Call
|
||||||
@Environment(\.scenePhase) var scenePhase
|
@Environment(\.scenePhase) var scenePhase
|
||||||
@State private var client: WebRTCClient? = nil
|
@State private var client: WebRTCClient? = nil
|
||||||
@State private var activeCall: WebRTCClient.Call? = nil
|
|
||||||
@State private var localRendererAspectRatio: CGFloat? = nil
|
@State private var localRendererAspectRatio: CGFloat? = nil
|
||||||
|
@State var remoteContentMode: UIView.ContentMode = .scaleAspectFill
|
||||||
@Binding var canConnectCall: Bool
|
@Binding var canConnectCall: Bool
|
||||||
@State var prevColorScheme: ColorScheme = .dark
|
@State var prevColorScheme: ColorScheme = .dark
|
||||||
@State var pipShown = false
|
@State var pipShown = false
|
||||||
@@ -27,24 +27,39 @@ struct ActiveCallView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack(alignment: .topLeading) {
|
ZStack(alignment: .topLeading) {
|
||||||
ZStack(alignment: .bottom) {
|
ZStack(alignment: .bottom) {
|
||||||
if let client = client, [call.peerMedia, call.localMedia].contains(.video), activeCall != nil {
|
if let client = client, call.hasVideo {
|
||||||
GeometryReader { g in
|
GeometryReader { g in
|
||||||
let width = g.size.width * 0.3
|
let width = g.size.width * 0.3
|
||||||
ZStack(alignment: .topTrailing) {
|
ZStack(alignment: .topTrailing) {
|
||||||
CallViewRemote(client: client, activeCall: $activeCall, activeCallViewIsCollapsed: $m.activeCallViewIsCollapsed, pipShown: $pipShown)
|
|
||||||
CallViewLocal(client: client, activeCall: $activeCall, localRendererAspectRatio: $localRendererAspectRatio, pipShown: $pipShown)
|
|
||||||
.cornerRadius(10)
|
|
||||||
.frame(width: width, height: width / (localRendererAspectRatio ?? 1))
|
|
||||||
.padding([.top, .trailing], 17)
|
|
||||||
ZStack(alignment: .center) {
|
ZStack(alignment: .center) {
|
||||||
// For some reason, when the view in GeometryReader and ZStack is visible, it steals clicks on a back button, so showing something on top like this with background color helps (.clear color doesn't work)
|
// For some reason, when the view in GeometryReader and ZStack is visible, it steals clicks on a back button, so showing something on top like this with background color helps (.clear color doesn't work)
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
.background(Color.primary.opacity(0.000001))
|
.background(Color.primary.opacity(0.000001))
|
||||||
|
|
||||||
|
CallViewRemote(client: client, call: call, activeCallViewIsCollapsed: $m.activeCallViewIsCollapsed, contentMode: $remoteContentMode, pipShown: $pipShown)
|
||||||
|
.onTapGesture {
|
||||||
|
remoteContentMode = remoteContentMode == .scaleAspectFill ? .scaleAspectFit : .scaleAspectFill
|
||||||
|
}
|
||||||
|
|
||||||
|
Group {
|
||||||
|
let localVideoTrack = client.activeCall?.localVideoTrack ?? client.notConnectedCall?.localCameraAndTrack?.1
|
||||||
|
if localVideoTrack != nil {
|
||||||
|
CallViewLocal(client: client, localRendererAspectRatio: $localRendererAspectRatio, pipShown: $pipShown)
|
||||||
|
.onDisappear {
|
||||||
|
localRendererAspectRatio = nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Rectangle().fill(.black)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.cornerRadius(10)
|
||||||
|
.frame(width: width, height: localRendererAspectRatio == nil ? (g.size.width < g.size.height ? width * 1.33 : width / 1.33) : width / (localRendererAspectRatio ?? 1))
|
||||||
|
.padding([.top, .trailing], 17)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let call = m.activeCall, let client = client, (!pipShown || !call.supportsVideo) {
|
if let call = m.activeCall, let client = client, (!pipShown || !call.hasVideo) {
|
||||||
ActiveCallOverlay(call: call, client: client)
|
ActiveCallOverlay(call: call, client: client)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,6 +69,9 @@ struct ActiveCallView: View {
|
|||||||
.onAppear {
|
.onAppear {
|
||||||
logger.debug("ActiveCallView: appear client is nil \(client == nil), scenePhase \(String(describing: scenePhase)), canConnectCall \(canConnectCall)")
|
logger.debug("ActiveCallView: appear client is nil \(client == nil), scenePhase \(String(describing: scenePhase)), canConnectCall \(canConnectCall)")
|
||||||
AppDelegate.keepScreenOn(true)
|
AppDelegate.keepScreenOn(true)
|
||||||
|
Task {
|
||||||
|
await askRequiredPermissions()
|
||||||
|
}
|
||||||
createWebRTCClient()
|
createWebRTCClient()
|
||||||
dismissAllSheets()
|
dismissAllSheets()
|
||||||
hideKeyboard()
|
hideKeyboard()
|
||||||
@@ -84,7 +102,7 @@ struct ActiveCallView: View {
|
|||||||
|
|
||||||
private func createWebRTCClient() {
|
private func createWebRTCClient() {
|
||||||
if client == nil && canConnectCall {
|
if client == nil && canConnectCall {
|
||||||
client = WebRTCClient($activeCall, { msg in await MainActor.run { processRtcMessage(msg: msg) } }, $localRendererAspectRatio)
|
client = WebRTCClient({ msg in await MainActor.run { processRtcMessage(msg: msg) } }, $localRendererAspectRatio)
|
||||||
Task {
|
Task {
|
||||||
await m.callCommand.setClient(client)
|
await m.callCommand.setClient(client)
|
||||||
}
|
}
|
||||||
@@ -99,7 +117,7 @@ struct ActiveCallView: View {
|
|||||||
logger.debug("ActiveCallView: response \(msg.resp.respType)")
|
logger.debug("ActiveCallView: response \(msg.resp.respType)")
|
||||||
switch msg.resp {
|
switch msg.resp {
|
||||||
case let .capabilities(capabilities):
|
case let .capabilities(capabilities):
|
||||||
let callType = CallType(media: call.localMedia, capabilities: capabilities)
|
let callType = CallType(media: call.initialCallType, capabilities: capabilities)
|
||||||
Task {
|
Task {
|
||||||
do {
|
do {
|
||||||
try await apiSendCallInvitation(call.contact, callType)
|
try await apiSendCallInvitation(call.contact, callType)
|
||||||
@@ -110,7 +128,7 @@ struct ActiveCallView: View {
|
|||||||
call.callState = .invitationSent
|
call.callState = .invitationSent
|
||||||
call.localCapabilities = capabilities
|
call.localCapabilities = capabilities
|
||||||
}
|
}
|
||||||
if call.supportsVideo && !AVAudioSession.sharedInstance().hasExternalAudioDevice() {
|
if call.hasVideo && !AVAudioSession.sharedInstance().hasExternalAudioDevice() {
|
||||||
try? AVAudioSession.sharedInstance().setCategory(.playback, options: [.allowBluetooth, .allowAirPlay, .allowBluetoothA2DP])
|
try? AVAudioSession.sharedInstance().setCategory(.playback, options: [.allowBluetooth, .allowAirPlay, .allowBluetoothA2DP])
|
||||||
}
|
}
|
||||||
CallSoundsPlayer.shared.startConnectingCallSound()
|
CallSoundsPlayer.shared.startConnectingCallSound()
|
||||||
@@ -120,7 +138,7 @@ struct ActiveCallView: View {
|
|||||||
Task {
|
Task {
|
||||||
do {
|
do {
|
||||||
try await apiSendCallOffer(call.contact, offer, iceCandidates,
|
try await apiSendCallOffer(call.contact, offer, iceCandidates,
|
||||||
media: call.localMedia, capabilities: capabilities)
|
media: call.initialCallType, capabilities: capabilities)
|
||||||
} catch {
|
} catch {
|
||||||
logger.error("apiSendCallOffer \(responseError(error))")
|
logger.error("apiSendCallOffer \(responseError(error))")
|
||||||
}
|
}
|
||||||
@@ -164,6 +182,9 @@ struct ActiveCallView: View {
|
|||||||
}
|
}
|
||||||
if state.connectionState == "closed" {
|
if state.connectionState == "closed" {
|
||||||
closeCallView(client)
|
closeCallView(client)
|
||||||
|
if let callUUID = m.activeCall?.callUUID {
|
||||||
|
CallController.shared.endCall(callUUID: callUUID)
|
||||||
|
}
|
||||||
m.activeCall = nil
|
m.activeCall = nil
|
||||||
m.activeCallViewIsCollapsed = false
|
m.activeCallViewIsCollapsed = false
|
||||||
}
|
}
|
||||||
@@ -182,6 +203,14 @@ struct ActiveCallView: View {
|
|||||||
CallSoundsPlayer.shared.vibrate(long: false)
|
CallSoundsPlayer.shared.vibrate(long: false)
|
||||||
wasConnected = true
|
wasConnected = true
|
||||||
}
|
}
|
||||||
|
case let .peerMedia(source, enabled):
|
||||||
|
switch source {
|
||||||
|
case .mic: call.peerMediaSources.mic = enabled
|
||||||
|
case .camera: call.peerMediaSources.camera = enabled
|
||||||
|
case .screenAudio: call.peerMediaSources.screenAudio = enabled
|
||||||
|
case .screenVideo: call.peerMediaSources.screenVideo = enabled
|
||||||
|
case .unknown: ()
|
||||||
|
}
|
||||||
case .ended:
|
case .ended:
|
||||||
closeCallView(client)
|
closeCallView(client)
|
||||||
call.callState = .ended
|
call.callState = .ended
|
||||||
@@ -226,6 +255,26 @@ struct ActiveCallView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func askRequiredPermissions() async {
|
||||||
|
let mic = await WebRTCClient.isAuthorized(for: .audio)
|
||||||
|
await MainActor.run {
|
||||||
|
call.localMediaSources.mic = mic
|
||||||
|
}
|
||||||
|
let cameraAuthorized = AVCaptureDevice.authorizationStatus(for: .video) == .authorized
|
||||||
|
var camera = call.initialCallType == .audio || cameraAuthorized
|
||||||
|
if call.initialCallType == .video && !cameraAuthorized {
|
||||||
|
camera = await WebRTCClient.isAuthorized(for: .video)
|
||||||
|
await MainActor.run {
|
||||||
|
if camera, let client {
|
||||||
|
client.setCameraEnabled(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !mic || !camera {
|
||||||
|
WebRTCClient.showUnauthorizedAlert(for: !mic ? .audio : .video)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func closeCallView(_ client: WebRTCClient) {
|
private func closeCallView(_ client: WebRTCClient) {
|
||||||
if m.activeCall != nil {
|
if m.activeCall != nil {
|
||||||
m.showCallView = false
|
m.showCallView = false
|
||||||
@@ -241,44 +290,16 @@ struct ActiveCallOverlay: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
switch call.localMedia {
|
switch call.hasVideo {
|
||||||
case .video:
|
case true:
|
||||||
videoCallInfoView(call)
|
videoCallInfoView(call)
|
||||||
.foregroundColor(.white)
|
.foregroundColor(.white)
|
||||||
.opacity(0.8)
|
.opacity(0.8)
|
||||||
.padding()
|
.padding(.horizontal)
|
||||||
|
// Fixed vertical padding required for preserving position of buttons row when changing audio-to-video and back in landscape orientation.
|
||||||
Spacer()
|
// Otherwise, bigger padding is added by SwiftUI when switching call types
|
||||||
|
.padding(.vertical, 10)
|
||||||
HStack {
|
case false:
|
||||||
toggleAudioButton()
|
|
||||||
Spacer()
|
|
||||||
if deviceManager.availableInputs.allSatisfy({ $0.portType == .builtInMic }) {
|
|
||||||
toggleSpeakerButton()
|
|
||||||
.frame(width: 40, height: 40)
|
|
||||||
} else if call.hasMedia {
|
|
||||||
AudioDevicePicker()
|
|
||||||
.scaleEffect(2)
|
|
||||||
.frame(maxWidth: 40, maxHeight: 40)
|
|
||||||
} else {
|
|
||||||
Color.clear.frame(width: 40, height: 40)
|
|
||||||
}
|
|
||||||
Spacer()
|
|
||||||
endCallButton()
|
|
||||||
Spacer()
|
|
||||||
if call.videoEnabled {
|
|
||||||
flipCameraButton()
|
|
||||||
} else {
|
|
||||||
Color.clear.frame(width: 40, height: 40)
|
|
||||||
}
|
|
||||||
Spacer()
|
|
||||||
toggleVideoButton()
|
|
||||||
}
|
|
||||||
.padding(.horizontal, 20)
|
|
||||||
.padding(.bottom, 16)
|
|
||||||
.frame(maxWidth: .infinity, alignment: .center)
|
|
||||||
|
|
||||||
case .audio:
|
|
||||||
ZStack(alignment: .topLeading) {
|
ZStack(alignment: .topLeading) {
|
||||||
Button {
|
Button {
|
||||||
chatModel.activeCallViewIsCollapsed = true
|
chatModel.activeCallViewIsCollapsed = true
|
||||||
@@ -293,35 +314,32 @@ struct ActiveCallOverlay: View {
|
|||||||
}
|
}
|
||||||
.foregroundColor(.white)
|
.foregroundColor(.white)
|
||||||
.opacity(0.8)
|
.opacity(0.8)
|
||||||
.padding()
|
.padding(.horizontal)
|
||||||
|
.padding(.vertical, 10)
|
||||||
.frame(maxHeight: .infinity)
|
.frame(maxHeight: .infinity)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
ZStack(alignment: .bottom) {
|
|
||||||
toggleAudioButton()
|
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
|
||||||
endCallButton()
|
|
||||||
// Check if the only input is microphone. And in this case show toggle button,
|
|
||||||
// If there are more inputs, it probably means something like bluetooth headphones are available
|
|
||||||
// and in this case show iOS button for choosing different output.
|
|
||||||
// There is no way to get available outputs, only inputs
|
|
||||||
if deviceManager.availableInputs.allSatisfy({ $0.portType == .builtInMic }) {
|
|
||||||
toggleSpeakerButton()
|
|
||||||
.frame(maxWidth: .infinity, alignment: .trailing)
|
|
||||||
} else if call.hasMedia {
|
|
||||||
AudioDevicePicker()
|
|
||||||
.scaleEffect(2)
|
|
||||||
.frame(maxWidth: 50, maxHeight: 40)
|
|
||||||
.frame(maxWidth: .infinity, alignment: .trailing)
|
|
||||||
} else {
|
|
||||||
Color.clear.frame(width: 50, height: 40)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(.bottom, 60)
|
|
||||||
.padding(.horizontal, 48)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
toggleMicButton()
|
||||||
|
Spacer()
|
||||||
|
audioDeviceButton()
|
||||||
|
Spacer()
|
||||||
|
endCallButton()
|
||||||
|
Spacer()
|
||||||
|
if call.localMediaSources.camera {
|
||||||
|
flipCameraButton()
|
||||||
|
} else {
|
||||||
|
Color.clear.frame(width: 60, height: 60)
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
toggleCameraButton()
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 20)
|
||||||
|
.padding(.bottom, 16)
|
||||||
|
.frame(maxWidth: 440, alignment: .center)
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
@@ -383,36 +401,54 @@ struct ActiveCallOverlay: View {
|
|||||||
|
|
||||||
private func endCallButton() -> some View {
|
private func endCallButton() -> some View {
|
||||||
let cc = CallController.shared
|
let cc = CallController.shared
|
||||||
return callButton("phone.down.fill", width: 60, height: 60) {
|
return callButton("phone.down.fill", .red, padding: 10) {
|
||||||
if let uuid = call.callUUID {
|
if let uuid = call.callUUID {
|
||||||
cc.endCall(callUUID: uuid)
|
cc.endCall(callUUID: uuid)
|
||||||
} else {
|
} else {
|
||||||
cc.endCall(call: call) {}
|
cc.endCall(call: call) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.foregroundColor(.red)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func toggleAudioButton() -> some View {
|
private func toggleMicButton() -> some View {
|
||||||
controlButton(call, call.audioEnabled ? "mic.fill" : "mic.slash") {
|
controlButton(call, call.localMediaSources.mic ? "mic.fill" : "mic.slash", padding: 14) {
|
||||||
Task {
|
Task {
|
||||||
client.setAudioEnabled(!call.audioEnabled)
|
if await WebRTCClient.isAuthorized(for: .audio) {
|
||||||
DispatchQueue.main.async {
|
client.setAudioEnabled(!call.localMediaSources.mic)
|
||||||
call.audioEnabled = !call.audioEnabled
|
} else { WebRTCClient.showUnauthorizedAlert(for: .audio) }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func audioDeviceButton() -> some View {
|
||||||
|
// Check if the only input is microphone. And in this case show toggle button,
|
||||||
|
// If there are more inputs, it probably means something like bluetooth headphones are available
|
||||||
|
// and in this case show iOS button for choosing different output.
|
||||||
|
// There is no way to get available outputs, only inputs
|
||||||
|
Group {
|
||||||
|
if deviceManager.availableInputs.allSatisfy({ $0.portType == .builtInMic }) {
|
||||||
|
toggleSpeakerButton()
|
||||||
|
} else {
|
||||||
|
audioDevicePickerButton()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onChange(of: call.localMediaSources.hasVideo) { hasVideo in
|
||||||
|
let current = AVAudioSession.sharedInstance().currentRoute.outputs.first?.portType
|
||||||
|
let speakerEnabled = current == .builtInSpeaker
|
||||||
|
let receiverEnabled = current == .builtInReceiver
|
||||||
|
// react automatically only when receiver were selected, otherwise keep an external device selected
|
||||||
|
if !speakerEnabled && hasVideo && receiverEnabled {
|
||||||
|
client.setSpeakerEnabledAndConfigureSession(!speakerEnabled, skipExternalDevice: true)
|
||||||
|
call.speakerEnabled = !speakerEnabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func toggleSpeakerButton() -> some View {
|
private func toggleSpeakerButton() -> some View {
|
||||||
controlButton(call, call.speakerEnabled ? "speaker.wave.2.fill" : "speaker.wave.1.fill") {
|
controlButton(call, !call.peerMediaSources.mic ? "speaker.slash" : call.speakerEnabled ? "speaker.wave.2.fill" : "speaker.wave.1.fill", padding: !call.peerMediaSources.mic ? 16 : call.speakerEnabled ? 15 : 17) {
|
||||||
Task {
|
let speakerEnabled = AVAudioSession.sharedInstance().currentRoute.outputs.first?.portType == .builtInSpeaker
|
||||||
let speakerEnabled = AVAudioSession.sharedInstance().currentRoute.outputs.first?.portType == .builtInSpeaker
|
client.setSpeakerEnabledAndConfigureSession(!speakerEnabled)
|
||||||
client.setSpeakerEnabledAndConfigureSession(!speakerEnabled)
|
call.speakerEnabled = !speakerEnabled
|
||||||
DispatchQueue.main.async {
|
|
||||||
call.speakerEnabled = !speakerEnabled
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
deviceManager.call = call
|
deviceManager.call = call
|
||||||
@@ -420,53 +456,67 @@ struct ActiveCallOverlay: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func toggleVideoButton() -> some View {
|
private func toggleCameraButton() -> some View {
|
||||||
controlButton(call, call.videoEnabled ? "video.fill" : "video.slash") {
|
controlButton(call, call.localMediaSources.camera ? "video.fill" : "video.slash", padding: call.localMediaSources.camera ? 16 : 14) {
|
||||||
Task {
|
Task {
|
||||||
client.setVideoEnabled(!call.videoEnabled)
|
if await WebRTCClient.isAuthorized(for: .video) {
|
||||||
DispatchQueue.main.async {
|
client.setCameraEnabled(!call.localMediaSources.camera)
|
||||||
call.videoEnabled = !call.videoEnabled
|
} else { WebRTCClient.showUnauthorizedAlert(for: .video) }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.disabled(call.initialCallType == .audio && client.activeCall?.peerHasOldVersion == true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder private func flipCameraButton() -> some View {
|
@ViewBuilder private func flipCameraButton() -> some View {
|
||||||
controlButton(call, "arrow.triangle.2.circlepath") {
|
controlButton(call, "arrow.triangle.2.circlepath", padding: 12) {
|
||||||
Task {
|
Task {
|
||||||
client.flipCamera()
|
if await WebRTCClient.isAuthorized(for: .video) {
|
||||||
|
client.flipCamera()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder private func controlButton(_ call: Call, _ imageName: String, _ perform: @escaping () -> Void) -> some View {
|
@ViewBuilder private func controlButton(_ call: Call, _ imageName: String, padding: CGFloat, _ perform: @escaping () -> Void) -> some View {
|
||||||
if call.hasMedia {
|
callButton(imageName, call.peerMediaSources.hasVideo ? Color.black.opacity(0.2) : Color.white.opacity(0.2), padding: padding, perform)
|
||||||
callButton(imageName, width: 50, height: 38, perform)
|
|
||||||
.foregroundColor(.white)
|
|
||||||
.opacity(0.85)
|
|
||||||
} else {
|
|
||||||
Color.clear.frame(width: 50, height: 38)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func callButton(_ imageName: String, width: CGFloat, height: CGFloat, _ perform: @escaping () -> Void) -> some View {
|
@ViewBuilder private func audioDevicePickerButton() -> some View {
|
||||||
|
AudioDevicePicker()
|
||||||
|
.opacity(0.8)
|
||||||
|
.scaleEffect(2)
|
||||||
|
.padding(10)
|
||||||
|
.frame(width: 60, height: 60)
|
||||||
|
.background(call.peerMediaSources.hasVideo ? Color.black.opacity(0.2) : Color.white.opacity(0.2))
|
||||||
|
.clipShape(.circle)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func callButton(_ imageName: String, _ background: Color, padding: CGFloat, _ perform: @escaping () -> Void) -> some View {
|
||||||
Button {
|
Button {
|
||||||
perform()
|
perform()
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: imageName)
|
Image(systemName: imageName)
|
||||||
.resizable()
|
.resizable()
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.frame(maxWidth: width, maxHeight: height)
|
.padding(padding)
|
||||||
|
.frame(width: 60, height: 60)
|
||||||
|
.background(background)
|
||||||
}
|
}
|
||||||
|
.foregroundColor(whiteColorWithAlpha)
|
||||||
|
.clipShape(.circle)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var whiteColorWithAlpha: Color {
|
||||||
|
get { Color(red: 204 / 255, green: 204 / 255, blue: 204 / 255) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ActiveCallOverlay_Previews: PreviewProvider {
|
struct ActiveCallOverlay_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
Group{
|
Group{
|
||||||
ActiveCallOverlay(call: Call(direction: .incoming, contact: Contact.sampleData, callUUID: UUID().uuidString.lowercased(), callState: .offerSent, localMedia: .video), client: WebRTCClient(Binding.constant(nil), { _ in }, Binding.constant(nil)))
|
ActiveCallOverlay(call: Call(direction: .incoming, contact: Contact.sampleData, callUUID: UUID().uuidString.lowercased(), callState: .offerSent, initialCallType: .video), client: WebRTCClient({ _ in }, Binding.constant(nil)))
|
||||||
.background(.black)
|
.background(.black)
|
||||||
ActiveCallOverlay(call: Call(direction: .incoming, contact: Contact.sampleData, callUUID: UUID().uuidString.lowercased(), callState: .offerSent, localMedia: .audio), client: WebRTCClient(Binding.constant(nil), { _ in }, Binding.constant(nil)))
|
ActiveCallOverlay(call: Call(direction: .incoming, contact: Contact.sampleData, callUUID: UUID().uuidString.lowercased(), callState: .offerSent, initialCallType: .audio), client: WebRTCClient({ _ in }, Binding.constant(nil)))
|
||||||
.background(.black)
|
.background(.black)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse
|
|||||||
}
|
}
|
||||||
|
|
||||||
func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
|
func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
|
||||||
if callManager.enableMedia(media: .audio, enable: !action.isMuted, callUUID: action.callUUID.uuidString.lowercased()) {
|
if callManager.enableMedia(source: .mic, enable: !action.isMuted, callUUID: action.callUUID.uuidString.lowercased()) {
|
||||||
action.fulfill()
|
action.fulfill()
|
||||||
} else {
|
} else {
|
||||||
action.fail()
|
action.fail()
|
||||||
@@ -121,8 +121,8 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse
|
|||||||
RTCAudioSession.sharedInstance().audioSessionDidActivate(audioSession)
|
RTCAudioSession.sharedInstance().audioSessionDidActivate(audioSession)
|
||||||
RTCAudioSession.sharedInstance().isAudioEnabled = true
|
RTCAudioSession.sharedInstance().isAudioEnabled = true
|
||||||
do {
|
do {
|
||||||
let supportsVideo = ChatModel.shared.activeCall?.supportsVideo == true
|
let hasVideo = ChatModel.shared.activeCall?.hasVideo == true
|
||||||
if supportsVideo {
|
if hasVideo {
|
||||||
try audioSession.setCategory(.playAndRecord, mode: .videoChat, options: [.defaultToSpeaker, .mixWithOthers, .allowBluetooth, .allowAirPlay, .allowBluetoothA2DP])
|
try audioSession.setCategory(.playAndRecord, mode: .videoChat, options: [.defaultToSpeaker, .mixWithOthers, .allowBluetooth, .allowAirPlay, .allowBluetoothA2DP])
|
||||||
} else {
|
} else {
|
||||||
try audioSession.setCategory(.playAndRecord, mode: .voiceChat, options: [.mixWithOthers, .allowBluetooth, .allowAirPlay, .allowBluetoothA2DP])
|
try audioSession.setCategory(.playAndRecord, mode: .voiceChat, options: [.mixWithOthers, .allowBluetooth, .allowAirPlay, .allowBluetoothA2DP])
|
||||||
@@ -133,7 +133,7 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse
|
|||||||
try? await Task.sleep(nanoseconds: UInt64(i) * 300_000000)
|
try? await Task.sleep(nanoseconds: UInt64(i) * 300_000000)
|
||||||
if let preferred = audioSession.preferredInputDevice() {
|
if let preferred = audioSession.preferredInputDevice() {
|
||||||
await MainActor.run { try? audioSession.setPreferredInput(preferred) }
|
await MainActor.run { try? audioSession.setPreferredInput(preferred) }
|
||||||
} else if supportsVideo {
|
} else if hasVideo {
|
||||||
await MainActor.run { try? audioSession.overrideOutputAudioPort(.speaker) }
|
await MainActor.run { try? audioSession.overrideOutputAudioPort(.speaker) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,11 +357,9 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse
|
|||||||
self.provider.reportCall(with: uuid, updated: update)
|
self.provider.reportCall(with: uuid, updated: update)
|
||||||
}
|
}
|
||||||
} else if callManager.startOutgoingCall(callUUID: callUUID) {
|
} else if callManager.startOutgoingCall(callUUID: callUUID) {
|
||||||
if callManager.startOutgoingCall(callUUID: callUUID) {
|
logger.debug("CallController.startCall: call started")
|
||||||
logger.debug("CallController.startCall: call started")
|
} else {
|
||||||
} else {
|
logger.error("CallController.startCall: no active call")
|
||||||
logger.error("CallController.startCall: no active call")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import SimpleXChat
|
|||||||
class CallManager {
|
class CallManager {
|
||||||
func newOutgoingCall(_ contact: Contact, _ media: CallMediaType) -> String {
|
func newOutgoingCall(_ contact: Contact, _ media: CallMediaType) -> String {
|
||||||
let uuid = UUID().uuidString.lowercased()
|
let uuid = UUID().uuidString.lowercased()
|
||||||
let call = Call(direction: .outgoing, contact: contact, callUUID: uuid, callState: .waitCapabilities, localMedia: media)
|
let call = Call(direction: .outgoing, contact: contact, callUUID: uuid, callState: .waitCapabilities, initialCallType: media)
|
||||||
call.speakerEnabled = media == .video
|
call.speakerEnabled = media == .video
|
||||||
ChatModel.shared.activeCall = call
|
ChatModel.shared.activeCall = call
|
||||||
return uuid
|
return uuid
|
||||||
@@ -22,7 +22,7 @@ class CallManager {
|
|||||||
let m = ChatModel.shared
|
let m = ChatModel.shared
|
||||||
if let call = m.activeCall, call.callUUID == callUUID {
|
if let call = m.activeCall, call.callUUID == callUUID {
|
||||||
m.showCallView = true
|
m.showCallView = true
|
||||||
Task { await m.callCommand.processCommand(.capabilities(media: call.localMedia)) }
|
Task { await m.callCommand.processCommand(.capabilities(media: call.initialCallType)) }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -44,7 +44,7 @@ class CallManager {
|
|||||||
contact: invitation.contact,
|
contact: invitation.contact,
|
||||||
callUUID: invitation.callUUID,
|
callUUID: invitation.callUUID,
|
||||||
callState: .invitationAccepted,
|
callState: .invitationAccepted,
|
||||||
localMedia: invitation.callType.media,
|
initialCallType: invitation.callType.media,
|
||||||
sharedKey: invitation.sharedKey
|
sharedKey: invitation.sharedKey
|
||||||
)
|
)
|
||||||
call.speakerEnabled = invitation.callType.media == .video
|
call.speakerEnabled = invitation.callType.media == .video
|
||||||
@@ -68,10 +68,10 @@ class CallManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func enableMedia(media: CallMediaType, enable: Bool, callUUID: String) -> Bool {
|
func enableMedia(source: CallMediaSource, enable: Bool, callUUID: String) -> Bool {
|
||||||
if let call = ChatModel.shared.activeCall, call.callUUID == callUUID {
|
if let call = ChatModel.shared.activeCall, call.callUUID == callUUID {
|
||||||
let m = ChatModel.shared
|
let m = ChatModel.shared
|
||||||
Task { await m.callCommand.processCommand(.media(media: media, enable: enable)) }
|
Task { await m.callCommand.processCommand(.media(source: source, enable: enable)) }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -10,40 +10,49 @@ import AVKit
|
|||||||
|
|
||||||
struct CallViewRemote: UIViewRepresentable {
|
struct CallViewRemote: UIViewRepresentable {
|
||||||
var client: WebRTCClient
|
var client: WebRTCClient
|
||||||
var activeCall: Binding<WebRTCClient.Call?>
|
@ObservedObject var call: Call
|
||||||
@State var enablePip: (Bool) -> Void = {_ in }
|
@State var enablePip: (Bool) -> Void = {_ in }
|
||||||
@Binding var activeCallViewIsCollapsed: Bool
|
@Binding var activeCallViewIsCollapsed: Bool
|
||||||
|
@Binding var contentMode: UIView.ContentMode
|
||||||
@Binding var pipShown: Bool
|
@Binding var pipShown: Bool
|
||||||
|
|
||||||
init(client: WebRTCClient, activeCall: Binding<WebRTCClient.Call?>, activeCallViewIsCollapsed: Binding<Bool>, pipShown: Binding<Bool>) {
|
|
||||||
self.client = client
|
|
||||||
self.activeCall = activeCall
|
|
||||||
self._activeCallViewIsCollapsed = activeCallViewIsCollapsed
|
|
||||||
self._pipShown = pipShown
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeUIView(context: Context) -> UIView {
|
func makeUIView(context: Context) -> UIView {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
if let call = activeCall.wrappedValue {
|
let remoteCameraRenderer = RTCMTLVideoView(frame: view.frame)
|
||||||
let remoteRenderer = RTCMTLVideoView(frame: view.frame)
|
remoteCameraRenderer.videoContentMode = contentMode
|
||||||
remoteRenderer.videoContentMode = .scaleAspectFill
|
remoteCameraRenderer.tag = 0
|
||||||
client.addRemoteRenderer(call, remoteRenderer)
|
|
||||||
addSubviewAndResize(remoteRenderer, into: view)
|
|
||||||
|
|
||||||
if AVPictureInPictureController.isPictureInPictureSupported() {
|
let screenVideo = call.peerMediaSources.screenVideo
|
||||||
makeViewWithRTCRenderer(call, remoteRenderer, view, context)
|
let remoteScreenRenderer = RTCMTLVideoView(frame: view.frame)
|
||||||
}
|
remoteScreenRenderer.videoContentMode = contentMode
|
||||||
|
remoteScreenRenderer.tag = 1
|
||||||
|
remoteScreenRenderer.alpha = screenVideo ? 1 : 0
|
||||||
|
|
||||||
|
context.coordinator.cameraRenderer = remoteCameraRenderer
|
||||||
|
context.coordinator.screenRenderer = remoteScreenRenderer
|
||||||
|
client.addRemoteCameraRenderer(remoteCameraRenderer)
|
||||||
|
client.addRemoteScreenRenderer(remoteScreenRenderer)
|
||||||
|
if screenVideo {
|
||||||
|
addSubviewAndResize(remoteScreenRenderer, remoteCameraRenderer, into: view)
|
||||||
|
} else {
|
||||||
|
addSubviewAndResize(remoteCameraRenderer, remoteScreenRenderer, into: view)
|
||||||
|
}
|
||||||
|
|
||||||
|
if AVPictureInPictureController.isPictureInPictureSupported() {
|
||||||
|
makeViewWithRTCRenderer(remoteCameraRenderer, remoteScreenRenderer, view, context)
|
||||||
}
|
}
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeViewWithRTCRenderer(_ call: WebRTCClient.Call, _ remoteRenderer: RTCMTLVideoView, _ view: UIView, _ context: Context) {
|
func makeViewWithRTCRenderer(_ remoteCameraRenderer: RTCMTLVideoView, _ remoteScreenRenderer: RTCMTLVideoView, _ view: UIView, _ context: Context) {
|
||||||
let pipRemoteRenderer = RTCMTLVideoView(frame: view.frame)
|
let pipRemoteCameraRenderer = RTCMTLVideoView(frame: view.frame)
|
||||||
pipRemoteRenderer.videoContentMode = .scaleAspectFill
|
pipRemoteCameraRenderer.videoContentMode = .scaleAspectFill
|
||||||
|
|
||||||
|
let pipRemoteScreenRenderer = RTCMTLVideoView(frame: view.frame)
|
||||||
|
pipRemoteScreenRenderer.videoContentMode = .scaleAspectFill
|
||||||
|
|
||||||
let pipVideoCallViewController = AVPictureInPictureVideoCallViewController()
|
let pipVideoCallViewController = AVPictureInPictureVideoCallViewController()
|
||||||
pipVideoCallViewController.preferredContentSize = CGSize(width: 1080, height: 1920)
|
pipVideoCallViewController.preferredContentSize = CGSize(width: 1080, height: 1920)
|
||||||
addSubviewAndResize(pipRemoteRenderer, into: pipVideoCallViewController.view)
|
|
||||||
let pipContentSource = AVPictureInPictureController.ContentSource(
|
let pipContentSource = AVPictureInPictureController.ContentSource(
|
||||||
activeVideoCallSourceView: view,
|
activeVideoCallSourceView: view,
|
||||||
contentViewController: pipVideoCallViewController
|
contentViewController: pipVideoCallViewController
|
||||||
@@ -55,7 +64,9 @@ struct CallViewRemote: UIViewRepresentable {
|
|||||||
context.coordinator.pipController = pipController
|
context.coordinator.pipController = pipController
|
||||||
context.coordinator.willShowHide = { show in
|
context.coordinator.willShowHide = { show in
|
||||||
if show {
|
if show {
|
||||||
client.addRemoteRenderer(call, pipRemoteRenderer)
|
client.addRemoteCameraRenderer(pipRemoteCameraRenderer)
|
||||||
|
client.addRemoteScreenRenderer(pipRemoteScreenRenderer)
|
||||||
|
context.coordinator.relayout()
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||||
activeCallViewIsCollapsed = true
|
activeCallViewIsCollapsed = true
|
||||||
}
|
}
|
||||||
@@ -67,13 +78,29 @@ struct CallViewRemote: UIViewRepresentable {
|
|||||||
}
|
}
|
||||||
context.coordinator.didShowHide = { show in
|
context.coordinator.didShowHide = { show in
|
||||||
if show {
|
if show {
|
||||||
remoteRenderer.isHidden = true
|
remoteCameraRenderer.isHidden = true
|
||||||
|
remoteScreenRenderer.isHidden = true
|
||||||
} else {
|
} else {
|
||||||
client.removeRemoteRenderer(call, pipRemoteRenderer)
|
client.removeRemoteCameraRenderer(pipRemoteCameraRenderer)
|
||||||
remoteRenderer.isHidden = false
|
client.removeRemoteScreenRenderer(pipRemoteScreenRenderer)
|
||||||
|
remoteCameraRenderer.isHidden = false
|
||||||
|
remoteScreenRenderer.isHidden = false
|
||||||
}
|
}
|
||||||
pipShown = show
|
pipShown = show
|
||||||
}
|
}
|
||||||
|
context.coordinator.relayout = {
|
||||||
|
let camera = call.peerMediaSources.camera
|
||||||
|
let screenVideo = call.peerMediaSources.screenVideo
|
||||||
|
pipRemoteCameraRenderer.alpha = camera ? 1 : 0
|
||||||
|
pipRemoteScreenRenderer.alpha = screenVideo ? 1 : 0
|
||||||
|
if screenVideo {
|
||||||
|
addSubviewAndResize(pipRemoteScreenRenderer, pipRemoteCameraRenderer, pip: true, into: pipVideoCallViewController.view)
|
||||||
|
} else {
|
||||||
|
addSubviewAndResize(pipRemoteCameraRenderer, pipRemoteScreenRenderer, pip: true, into: pipVideoCallViewController.view)
|
||||||
|
}
|
||||||
|
(pipVideoCallViewController.view.subviews[0] as! RTCMTLVideoView).videoContentMode = contentMode
|
||||||
|
(pipVideoCallViewController.view.subviews[1] as! RTCMTLVideoView).videoContentMode = .scaleAspectFill
|
||||||
|
}
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
enablePip = { enable in
|
enablePip = { enable in
|
||||||
if enable != pipShown /* pipController.isPictureInPictureActive */ {
|
if enable != pipShown /* pipController.isPictureInPictureActive */ {
|
||||||
@@ -88,23 +115,49 @@ struct CallViewRemote: UIViewRepresentable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makeCoordinator() -> Coordinator {
|
func makeCoordinator() -> Coordinator {
|
||||||
Coordinator()
|
Coordinator(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateUIView(_ view: UIView, context: Context) {
|
func updateUIView(_ view: UIView, context: Context) {
|
||||||
logger.debug("CallView.updateUIView remote")
|
logger.debug("CallView.updateUIView remote")
|
||||||
|
let camera = view.subviews.first(where: { $0.tag == 0 })!
|
||||||
|
let screen = view.subviews.first(where: { $0.tag == 1 })!
|
||||||
|
let screenVideo = call.peerMediaSources.screenVideo
|
||||||
|
if screenVideo && screen.alpha == 0 {
|
||||||
|
screen.alpha = 1
|
||||||
|
addSubviewAndResize(screen, camera, into: view)
|
||||||
|
} else if !screenVideo && screen.alpha == 1 {
|
||||||
|
screen.alpha = 0
|
||||||
|
addSubviewAndResize(camera, screen, into: view)
|
||||||
|
}
|
||||||
|
(view.subviews[0] as! RTCMTLVideoView).videoContentMode = contentMode
|
||||||
|
(view.subviews[1] as! RTCMTLVideoView).videoContentMode = .scaleAspectFill
|
||||||
|
|
||||||
|
camera.alpha = call.peerMediaSources.camera ? 1 : 0
|
||||||
|
screen.alpha = call.peerMediaSources.screenVideo ? 1 : 0
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
if activeCallViewIsCollapsed != pipShown {
|
if activeCallViewIsCollapsed != pipShown {
|
||||||
enablePip(activeCallViewIsCollapsed)
|
enablePip(activeCallViewIsCollapsed)
|
||||||
|
} else if pipShown {
|
||||||
|
context.coordinator.relayout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Coordinator
|
// MARK: - Coordinator
|
||||||
class Coordinator: NSObject, AVPictureInPictureControllerDelegate {
|
class Coordinator: NSObject, AVPictureInPictureControllerDelegate {
|
||||||
|
var cameraRenderer: RTCMTLVideoView?
|
||||||
|
var screenRenderer: RTCMTLVideoView?
|
||||||
|
var client: WebRTCClient
|
||||||
var pipController: AVPictureInPictureController? = nil
|
var pipController: AVPictureInPictureController? = nil
|
||||||
var willShowHide: (Bool) -> Void = { _ in }
|
var willShowHide: (Bool) -> Void = { _ in }
|
||||||
var didShowHide: (Bool) -> Void = { _ in }
|
var didShowHide: (Bool) -> Void = { _ in }
|
||||||
|
var relayout: () -> Void = {}
|
||||||
|
|
||||||
|
required init(_ client: WebRTCClient) {
|
||||||
|
self.client = client
|
||||||
|
}
|
||||||
|
|
||||||
func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
|
func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
|
||||||
willShowHide(true)
|
willShowHide(true)
|
||||||
@@ -127,11 +180,20 @@ struct CallViewRemote: UIViewRepresentable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
// TODO: deinit is not called when changing call type from audio to video and back,
|
||||||
|
// which causes many renderers can be created and added to stream (if enabling/disabling
|
||||||
|
// video while not yet connected in outgoing call)
|
||||||
pipController?.stopPictureInPicture()
|
pipController?.stopPictureInPicture()
|
||||||
pipController?.canStartPictureInPictureAutomaticallyFromInline = false
|
pipController?.canStartPictureInPictureAutomaticallyFromInline = false
|
||||||
pipController?.contentSource = nil
|
pipController?.contentSource = nil
|
||||||
pipController?.delegate = nil
|
pipController?.delegate = nil
|
||||||
pipController = nil
|
pipController = nil
|
||||||
|
if let cameraRenderer {
|
||||||
|
client.removeRemoteCameraRenderer(cameraRenderer)
|
||||||
|
}
|
||||||
|
if let screenRenderer {
|
||||||
|
client.removeRemoteScreenRenderer(screenRenderer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,51 +210,109 @@ struct CallViewRemote: UIViewRepresentable {
|
|||||||
|
|
||||||
struct CallViewLocal: UIViewRepresentable {
|
struct CallViewLocal: UIViewRepresentable {
|
||||||
var client: WebRTCClient
|
var client: WebRTCClient
|
||||||
var activeCall: Binding<WebRTCClient.Call?>
|
|
||||||
var localRendererAspectRatio: Binding<CGFloat?>
|
var localRendererAspectRatio: Binding<CGFloat?>
|
||||||
@State var pipStateChanged: (Bool) -> Void = {_ in }
|
@State var pipStateChanged: (Bool) -> Void = {_ in }
|
||||||
@Binding var pipShown: Bool
|
@Binding var pipShown: Bool
|
||||||
|
|
||||||
init(client: WebRTCClient, activeCall: Binding<WebRTCClient.Call?>, localRendererAspectRatio: Binding<CGFloat?>, pipShown: Binding<Bool>) {
|
init(client: WebRTCClient, localRendererAspectRatio: Binding<CGFloat?>, pipShown: Binding<Bool>) {
|
||||||
self.client = client
|
self.client = client
|
||||||
self.activeCall = activeCall
|
|
||||||
self.localRendererAspectRatio = localRendererAspectRatio
|
self.localRendererAspectRatio = localRendererAspectRatio
|
||||||
self._pipShown = pipShown
|
self._pipShown = pipShown
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeUIView(context: Context) -> UIView {
|
func makeUIView(context: Context) -> UIView {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
if let call = activeCall.wrappedValue {
|
let localRenderer = RTCEAGLVideoView(frame: .zero)
|
||||||
let localRenderer = RTCEAGLVideoView(frame: .zero)
|
context.coordinator.renderer = localRenderer
|
||||||
client.addLocalRenderer(call, localRenderer)
|
client.addLocalRenderer(localRenderer)
|
||||||
client.startCaptureLocalVideo(call)
|
addSubviewAndResize(localRenderer, nil, into: view)
|
||||||
addSubviewAndResize(localRenderer, into: view)
|
DispatchQueue.main.async {
|
||||||
DispatchQueue.main.async {
|
pipStateChanged = { shown in
|
||||||
pipStateChanged = { shown in
|
localRenderer.isHidden = shown
|
||||||
localRenderer.isHidden = shown
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeCoordinator() -> Coordinator {
|
||||||
|
Coordinator(client)
|
||||||
|
}
|
||||||
|
|
||||||
func updateUIView(_ view: UIView, context: Context) {
|
func updateUIView(_ view: UIView, context: Context) {
|
||||||
logger.debug("CallView.updateUIView local")
|
logger.debug("CallView.updateUIView local")
|
||||||
pipStateChanged(pipShown)
|
pipStateChanged(pipShown)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Coordinator
|
||||||
|
class Coordinator: NSObject, AVPictureInPictureControllerDelegate {
|
||||||
|
var renderer: RTCEAGLVideoView?
|
||||||
|
var client: WebRTCClient
|
||||||
|
|
||||||
|
required init(_ client: WebRTCClient) {
|
||||||
|
self.client = client
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
if let renderer {
|
||||||
|
client.removeLocalRenderer(renderer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addSubviewAndResize(_ view: UIView, into containerView: UIView) {
|
private func addSubviewAndResize(_ fullscreen: UIView, _ end: UIView?, pip: Bool = false, into containerView: UIView) {
|
||||||
containerView.addSubview(view)
|
if containerView.subviews.firstIndex(of: fullscreen) == 0 && ((end == nil && containerView.subviews.count == 1) || (end != nil && containerView.subviews.firstIndex(of: end!) == 1)) {
|
||||||
view.translatesAutoresizingMaskIntoConstraints = false
|
// Nothing to do, elements on their places
|
||||||
containerView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view]|",
|
return
|
||||||
options: [],
|
}
|
||||||
metrics: nil,
|
containerView.removeConstraints(containerView.constraints)
|
||||||
views: ["view": view]))
|
containerView.subviews.forEach { sub in sub.removeFromSuperview()}
|
||||||
|
|
||||||
containerView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[view]|",
|
containerView.addSubview(fullscreen)
|
||||||
|
fullscreen.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
fullscreen.layer.cornerRadius = 0
|
||||||
|
fullscreen.layer.masksToBounds = false
|
||||||
|
|
||||||
|
if let end {
|
||||||
|
containerView.addSubview(end)
|
||||||
|
end.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
end.layer.cornerRadius = pip ? 8 : 10
|
||||||
|
end.layer.masksToBounds = true
|
||||||
|
}
|
||||||
|
|
||||||
|
let constraintFullscreenV = NSLayoutConstraint.constraints(
|
||||||
|
withVisualFormat: "V:|[fullscreen]|",
|
||||||
options: [],
|
options: [],
|
||||||
metrics: nil,
|
metrics: nil,
|
||||||
views: ["view": view]))
|
views: ["fullscreen": fullscreen]
|
||||||
|
)
|
||||||
|
let constraintFullscreenH = NSLayoutConstraint.constraints(
|
||||||
|
withVisualFormat: "H:|[fullscreen]|",
|
||||||
|
options: [],
|
||||||
|
metrics: nil,
|
||||||
|
views: ["fullscreen": fullscreen]
|
||||||
|
)
|
||||||
|
|
||||||
|
containerView.addConstraints(constraintFullscreenV)
|
||||||
|
containerView.addConstraints(constraintFullscreenH)
|
||||||
|
|
||||||
|
if let end {
|
||||||
|
let constraintEndWidth = NSLayoutConstraint(
|
||||||
|
item: end, attribute: .width, relatedBy: .equal, toItem: containerView, attribute: .width, multiplier: pip ? 0.5 : 0.3, constant: 0
|
||||||
|
)
|
||||||
|
let constraintEndHeight = NSLayoutConstraint(
|
||||||
|
item: end, attribute: .height, relatedBy: .equal, toItem: containerView, attribute: .width, multiplier: pip ? 0.5 * 1.33 : 0.3 * 1.33, constant: 0
|
||||||
|
)
|
||||||
|
let constraintEndX = NSLayoutConstraint(
|
||||||
|
item: end, attribute: .leading, relatedBy: .equal, toItem: containerView, attribute: .trailing, multiplier: pip ? 0.5 : 0.7, constant: pip ? -8 : -17
|
||||||
|
)
|
||||||
|
let constraintEndY = NSLayoutConstraint(
|
||||||
|
item: end, attribute: .bottom, relatedBy: .equal, toItem: containerView, attribute: .bottom, multiplier: 1, constant: pip ? -8 : -92
|
||||||
|
)
|
||||||
|
containerView.addConstraint(constraintEndWidth)
|
||||||
|
containerView.addConstraint(constraintEndHeight)
|
||||||
|
containerView.addConstraint(constraintEndX)
|
||||||
|
containerView.addConstraint(constraintEndY)
|
||||||
|
}
|
||||||
containerView.layoutIfNeeded()
|
containerView.layoutIfNeeded()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,13 @@ class Call: ObservableObject, Equatable {
|
|||||||
var direction: CallDirection
|
var direction: CallDirection
|
||||||
var contact: Contact
|
var contact: Contact
|
||||||
var callUUID: String?
|
var callUUID: String?
|
||||||
var localMedia: CallMediaType
|
var initialCallType: CallMediaType
|
||||||
|
@Published var localMediaSources: CallMediaSources
|
||||||
@Published var callState: CallState
|
@Published var callState: CallState
|
||||||
@Published var localCapabilities: CallCapabilities?
|
@Published var localCapabilities: CallCapabilities?
|
||||||
@Published var peerMedia: CallMediaType?
|
@Published var peerMediaSources: CallMediaSources = CallMediaSources()
|
||||||
@Published var sharedKey: String?
|
@Published var sharedKey: String?
|
||||||
@Published var audioEnabled = true
|
|
||||||
@Published var speakerEnabled = false
|
@Published var speakerEnabled = false
|
||||||
@Published var videoEnabled: Bool
|
|
||||||
@Published var connectionInfo: ConnectionInfo?
|
@Published var connectionInfo: ConnectionInfo?
|
||||||
@Published var connectedAt: Date? = nil
|
@Published var connectedAt: Date? = nil
|
||||||
|
|
||||||
@@ -35,20 +34,22 @@ class Call: ObservableObject, Equatable {
|
|||||||
contact: Contact,
|
contact: Contact,
|
||||||
callUUID: String?,
|
callUUID: String?,
|
||||||
callState: CallState,
|
callState: CallState,
|
||||||
localMedia: CallMediaType,
|
initialCallType: CallMediaType,
|
||||||
sharedKey: String? = nil
|
sharedKey: String? = nil
|
||||||
) {
|
) {
|
||||||
self.direction = direction
|
self.direction = direction
|
||||||
self.contact = contact
|
self.contact = contact
|
||||||
self.callUUID = callUUID
|
self.callUUID = callUUID
|
||||||
self.callState = callState
|
self.callState = callState
|
||||||
self.localMedia = localMedia
|
self.initialCallType = initialCallType
|
||||||
self.sharedKey = sharedKey
|
self.sharedKey = sharedKey
|
||||||
self.videoEnabled = localMedia == .video
|
self.localMediaSources = CallMediaSources(
|
||||||
|
mic: AVCaptureDevice.authorizationStatus(for: .audio) == .authorized,
|
||||||
|
camera: initialCallType == .video && AVCaptureDevice.authorizationStatus(for: .video) == .authorized)
|
||||||
}
|
}
|
||||||
|
|
||||||
var encrypted: Bool { get { localEncrypted && sharedKey != nil } }
|
var encrypted: Bool { get { localEncrypted && sharedKey != nil } }
|
||||||
var localEncrypted: Bool { get { localCapabilities?.encryption ?? false } }
|
private var localEncrypted: Bool { get { localCapabilities?.encryption ?? false } }
|
||||||
var encryptionStatus: LocalizedStringKey {
|
var encryptionStatus: LocalizedStringKey {
|
||||||
get {
|
get {
|
||||||
switch callState {
|
switch callState {
|
||||||
@@ -59,8 +60,7 @@ class Call: ObservableObject, Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var hasMedia: Bool { get { callState == .offerSent || callState == .negotiated || callState == .connected } }
|
var hasVideo: Bool { get { localMediaSources.hasVideo || peerMediaSources.hasVideo } }
|
||||||
var supportsVideo: Bool { get { peerMedia == .video || localMedia == .video } }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CallDirection {
|
enum CallDirection {
|
||||||
@@ -105,18 +105,28 @@ struct WVAPIMessage: Equatable, Decodable, Encodable {
|
|||||||
var command: WCallCommand?
|
var command: WCallCommand?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CallMediaSources: Equatable, Codable {
|
||||||
|
var mic: Bool = false
|
||||||
|
var camera: Bool = false
|
||||||
|
var screenAudio: Bool = false
|
||||||
|
var screenVideo: Bool = false
|
||||||
|
|
||||||
|
var hasVideo: Bool { get { camera || screenVideo } }
|
||||||
|
}
|
||||||
|
|
||||||
enum WCallCommand: Equatable, Encodable, Decodable {
|
enum WCallCommand: Equatable, Encodable, Decodable {
|
||||||
case capabilities(media: CallMediaType)
|
case capabilities(media: CallMediaType)
|
||||||
case start(media: CallMediaType, aesKey: String? = nil, iceServers: [RTCIceServer]? = nil, relay: Bool? = nil)
|
case start(media: CallMediaType, aesKey: String? = nil, iceServers: [RTCIceServer]? = nil, relay: Bool? = nil)
|
||||||
case offer(offer: String, iceCandidates: String, media: CallMediaType, aesKey: String? = nil, iceServers: [RTCIceServer]? = nil, relay: Bool? = nil)
|
case offer(offer: String, iceCandidates: String, media: CallMediaType, aesKey: String? = nil, iceServers: [RTCIceServer]? = nil, relay: Bool? = nil)
|
||||||
case answer(answer: String, iceCandidates: String)
|
case answer(answer: String, iceCandidates: String)
|
||||||
case ice(iceCandidates: String)
|
case ice(iceCandidates: String)
|
||||||
case media(media: CallMediaType, enable: Bool)
|
case media(source: CallMediaSource, enable: Bool)
|
||||||
case end
|
case end
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case type
|
case type
|
||||||
case media
|
case media
|
||||||
|
case source
|
||||||
case aesKey
|
case aesKey
|
||||||
case offer
|
case offer
|
||||||
case answer
|
case answer
|
||||||
@@ -167,9 +177,9 @@ enum WCallCommand: Equatable, Encodable, Decodable {
|
|||||||
case let .ice(iceCandidates):
|
case let .ice(iceCandidates):
|
||||||
try container.encode("ice", forKey: .type)
|
try container.encode("ice", forKey: .type)
|
||||||
try container.encode(iceCandidates, forKey: .iceCandidates)
|
try container.encode(iceCandidates, forKey: .iceCandidates)
|
||||||
case let .media(media, enable):
|
case let .media(source, enable):
|
||||||
try container.encode("media", forKey: .type)
|
try container.encode("media", forKey: .type)
|
||||||
try container.encode(media, forKey: .media)
|
try container.encode(source, forKey: .media)
|
||||||
try container.encode(enable, forKey: .enable)
|
try container.encode(enable, forKey: .enable)
|
||||||
case .end:
|
case .end:
|
||||||
try container.encode("end", forKey: .type)
|
try container.encode("end", forKey: .type)
|
||||||
@@ -205,9 +215,9 @@ enum WCallCommand: Equatable, Encodable, Decodable {
|
|||||||
let iceCandidates = try container.decode(String.self, forKey: CodingKeys.iceCandidates)
|
let iceCandidates = try container.decode(String.self, forKey: CodingKeys.iceCandidates)
|
||||||
self = .ice(iceCandidates: iceCandidates)
|
self = .ice(iceCandidates: iceCandidates)
|
||||||
case "media":
|
case "media":
|
||||||
let media = try container.decode(CallMediaType.self, forKey: CodingKeys.media)
|
let source = try container.decode(CallMediaSource.self, forKey: CodingKeys.source)
|
||||||
let enable = try container.decode(Bool.self, forKey: CodingKeys.enable)
|
let enable = try container.decode(Bool.self, forKey: CodingKeys.enable)
|
||||||
self = .media(media: media, enable: enable)
|
self = .media(source: source, enable: enable)
|
||||||
case "end":
|
case "end":
|
||||||
self = .end
|
self = .end
|
||||||
default:
|
default:
|
||||||
@@ -224,6 +234,7 @@ enum WCallResponse: Equatable, Decodable {
|
|||||||
case ice(iceCandidates: String)
|
case ice(iceCandidates: String)
|
||||||
case connection(state: ConnectionState)
|
case connection(state: ConnectionState)
|
||||||
case connected(connectionInfo: ConnectionInfo)
|
case connected(connectionInfo: ConnectionInfo)
|
||||||
|
case peerMedia(source: CallMediaSource, enabled: Bool)
|
||||||
case ended
|
case ended
|
||||||
case ok
|
case ok
|
||||||
case error(message: String)
|
case error(message: String)
|
||||||
@@ -238,6 +249,8 @@ enum WCallResponse: Equatable, Decodable {
|
|||||||
case state
|
case state
|
||||||
case connectionInfo
|
case connectionInfo
|
||||||
case message
|
case message
|
||||||
|
case source
|
||||||
|
case enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
var respType: String {
|
var respType: String {
|
||||||
@@ -249,6 +262,7 @@ enum WCallResponse: Equatable, Decodable {
|
|||||||
case .ice: return "ice"
|
case .ice: return "ice"
|
||||||
case .connection: return "connection"
|
case .connection: return "connection"
|
||||||
case .connected: return "connected"
|
case .connected: return "connected"
|
||||||
|
case .peerMedia: return "peerMedia"
|
||||||
case .ended: return "ended"
|
case .ended: return "ended"
|
||||||
case .ok: return "ok"
|
case .ok: return "ok"
|
||||||
case .error: return "error"
|
case .error: return "error"
|
||||||
@@ -283,6 +297,10 @@ enum WCallResponse: Equatable, Decodable {
|
|||||||
case "connected":
|
case "connected":
|
||||||
let connectionInfo = try container.decode(ConnectionInfo.self, forKey: CodingKeys.connectionInfo)
|
let connectionInfo = try container.decode(ConnectionInfo.self, forKey: CodingKeys.connectionInfo)
|
||||||
self = .connected(connectionInfo: connectionInfo)
|
self = .connected(connectionInfo: connectionInfo)
|
||||||
|
case "peerMedia":
|
||||||
|
let source = try container.decode(CallMediaSource.self, forKey: CodingKeys.source)
|
||||||
|
let enabled = try container.decode(Bool.self, forKey: CodingKeys.enabled)
|
||||||
|
self = .peerMedia(source: source, enabled: enabled)
|
||||||
case "ended":
|
case "ended":
|
||||||
self = .ended
|
self = .ended
|
||||||
case "ok":
|
case "ok":
|
||||||
@@ -324,6 +342,10 @@ extension WCallResponse: Encodable {
|
|||||||
case let .connected(connectionInfo):
|
case let .connected(connectionInfo):
|
||||||
try container.encode("connected", forKey: .type)
|
try container.encode("connected", forKey: .type)
|
||||||
try container.encode(connectionInfo, forKey: .connectionInfo)
|
try container.encode(connectionInfo, forKey: .connectionInfo)
|
||||||
|
case let .peerMedia(source, enabled):
|
||||||
|
try container.encode("peerMedia", forKey: .type)
|
||||||
|
try container.encode(source, forKey: .source)
|
||||||
|
try container.encode(enabled, forKey: .enabled)
|
||||||
case .ended:
|
case .ended:
|
||||||
try container.encode("ended", forKey: .type)
|
try container.encode("ended", forKey: .type)
|
||||||
case .ok:
|
case .ok:
|
||||||
@@ -376,7 +398,7 @@ actor WebRTCCommandProcessor {
|
|||||||
func shouldRunCommand(_ client: WebRTCClient, _ c: WCallCommand) -> Bool {
|
func shouldRunCommand(_ client: WebRTCClient, _ c: WCallCommand) -> Bool {
|
||||||
switch c {
|
switch c {
|
||||||
case .capabilities, .start, .offer, .end: true
|
case .capabilities, .start, .offer, .end: true
|
||||||
default: client.activeCall.wrappedValue != nil
|
default: client.activeCall != nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,15 +23,24 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
struct Call {
|
struct Call {
|
||||||
var connection: RTCPeerConnection
|
var connection: RTCPeerConnection
|
||||||
var iceCandidates: IceCandidates
|
var iceCandidates: IceCandidates
|
||||||
var localMedia: CallMediaType
|
|
||||||
var localCamera: RTCVideoCapturer?
|
var localCamera: RTCVideoCapturer?
|
||||||
var localVideoSource: RTCVideoSource?
|
var localAudioTrack: RTCAudioTrack?
|
||||||
var localStream: RTCVideoTrack?
|
var localVideoTrack: RTCVideoTrack?
|
||||||
var remoteStream: RTCVideoTrack?
|
var remoteAudioTrack: RTCAudioTrack?
|
||||||
var device: AVCaptureDevice.Position = .front
|
var remoteVideoTrack: RTCVideoTrack?
|
||||||
|
var remoteScreenAudioTrack: RTCAudioTrack?
|
||||||
|
var remoteScreenVideoTrack: RTCVideoTrack?
|
||||||
|
var device: AVCaptureDevice.Position
|
||||||
var aesKey: String?
|
var aesKey: String?
|
||||||
var frameEncryptor: RTCFrameEncryptor?
|
var frameEncryptor: RTCFrameEncryptor?
|
||||||
var frameDecryptor: RTCFrameDecryptor?
|
var frameDecryptor: RTCFrameDecryptor?
|
||||||
|
var peerHasOldVersion: Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NotConnectedCall {
|
||||||
|
var audioTrack: RTCAudioTrack?
|
||||||
|
var localCameraAndTrack: (RTCVideoCapturer, RTCVideoTrack)?
|
||||||
|
var device: AVCaptureDevice.Position = .front
|
||||||
}
|
}
|
||||||
|
|
||||||
actor IceCandidates {
|
actor IceCandidates {
|
||||||
@@ -51,17 +60,20 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
private let rtcAudioSession = RTCAudioSession.sharedInstance()
|
private let rtcAudioSession = RTCAudioSession.sharedInstance()
|
||||||
private let audioQueue = DispatchQueue(label: "chat.simplex.app.audio")
|
private let audioQueue = DispatchQueue(label: "chat.simplex.app.audio")
|
||||||
private var sendCallResponse: (WVAPIMessage) async -> Void
|
private var sendCallResponse: (WVAPIMessage) async -> Void
|
||||||
var activeCall: Binding<Call?>
|
var activeCall: Call?
|
||||||
|
var notConnectedCall: NotConnectedCall?
|
||||||
private var localRendererAspectRatio: Binding<CGFloat?>
|
private var localRendererAspectRatio: Binding<CGFloat?>
|
||||||
|
|
||||||
|
var cameraRenderers: [RTCVideoRenderer] = []
|
||||||
|
var screenRenderers: [RTCVideoRenderer] = []
|
||||||
|
|
||||||
@available(*, unavailable)
|
@available(*, unavailable)
|
||||||
override init() {
|
override init() {
|
||||||
fatalError("Unimplemented")
|
fatalError("Unimplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
required init(_ activeCall: Binding<Call?>, _ sendCallResponse: @escaping (WVAPIMessage) async -> Void, _ localRendererAspectRatio: Binding<CGFloat?>) {
|
required init(_ sendCallResponse: @escaping (WVAPIMessage) async -> Void, _ localRendererAspectRatio: Binding<CGFloat?>) {
|
||||||
self.sendCallResponse = sendCallResponse
|
self.sendCallResponse = sendCallResponse
|
||||||
self.activeCall = activeCall
|
|
||||||
self.localRendererAspectRatio = localRendererAspectRatio
|
self.localRendererAspectRatio = localRendererAspectRatio
|
||||||
rtcAudioSession.useManualAudio = CallController.useCallKit()
|
rtcAudioSession.useManualAudio = CallController.useCallKit()
|
||||||
rtcAudioSession.isAudioEnabled = !CallController.useCallKit()
|
rtcAudioSession.isAudioEnabled = !CallController.useCallKit()
|
||||||
@@ -78,39 +90,45 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
func initializeCall(_ iceServers: [WebRTC.RTCIceServer]?, _ mediaType: CallMediaType, _ aesKey: String?, _ relay: Bool?) -> Call {
|
func initializeCall(_ iceServers: [WebRTC.RTCIceServer]?, _ mediaType: CallMediaType, _ aesKey: String?, _ relay: Bool?) -> Call {
|
||||||
let connection = createPeerConnection(iceServers ?? getWebRTCIceServers() ?? defaultIceServers, relay)
|
let connection = createPeerConnection(iceServers ?? getWebRTCIceServers() ?? defaultIceServers, relay)
|
||||||
connection.delegate = self
|
connection.delegate = self
|
||||||
createAudioSender(connection)
|
let device = notConnectedCall?.device ?? .front
|
||||||
var localStream: RTCVideoTrack? = nil
|
|
||||||
var remoteStream: RTCVideoTrack? = nil
|
|
||||||
var localCamera: RTCVideoCapturer? = nil
|
var localCamera: RTCVideoCapturer? = nil
|
||||||
var localVideoSource: RTCVideoSource? = nil
|
var localAudioTrack: RTCAudioTrack? = nil
|
||||||
if mediaType == .video {
|
var localVideoTrack: RTCVideoTrack? = nil
|
||||||
(localStream, remoteStream, localCamera, localVideoSource) = createVideoSender(connection)
|
if let localCameraAndTrack = notConnectedCall?.localCameraAndTrack {
|
||||||
|
(localCamera, localVideoTrack) = localCameraAndTrack
|
||||||
|
} else if notConnectedCall == nil && mediaType == .video {
|
||||||
|
(localCamera, localVideoTrack) = createVideoTrackAndStartCapture(device)
|
||||||
}
|
}
|
||||||
|
if let audioTrack = notConnectedCall?.audioTrack {
|
||||||
|
localAudioTrack = audioTrack
|
||||||
|
} else if notConnectedCall == nil {
|
||||||
|
localAudioTrack = createAudioTrack()
|
||||||
|
}
|
||||||
|
notConnectedCall?.localCameraAndTrack = nil
|
||||||
|
notConnectedCall?.audioTrack = nil
|
||||||
|
|
||||||
var frameEncryptor: RTCFrameEncryptor? = nil
|
var frameEncryptor: RTCFrameEncryptor? = nil
|
||||||
var frameDecryptor: RTCFrameDecryptor? = nil
|
var frameDecryptor: RTCFrameDecryptor? = nil
|
||||||
if aesKey != nil {
|
if aesKey != nil {
|
||||||
let encryptor = RTCFrameEncryptor.init(sizeChange: Int32(WebRTCClient.ivTagBytes))
|
let encryptor = RTCFrameEncryptor.init(sizeChange: Int32(WebRTCClient.ivTagBytes))
|
||||||
encryptor.delegate = self
|
encryptor.delegate = self
|
||||||
frameEncryptor = encryptor
|
frameEncryptor = encryptor
|
||||||
connection.senders.forEach { $0.setRtcFrameEncryptor(encryptor) }
|
|
||||||
|
|
||||||
let decryptor = RTCFrameDecryptor.init(sizeChange: -Int32(WebRTCClient.ivTagBytes))
|
let decryptor = RTCFrameDecryptor.init(sizeChange: -Int32(WebRTCClient.ivTagBytes))
|
||||||
decryptor.delegate = self
|
decryptor.delegate = self
|
||||||
frameDecryptor = decryptor
|
frameDecryptor = decryptor
|
||||||
// Has no video receiver in outgoing call if applied here, see [peerConnection(_ connection: RTCPeerConnection, didChange newState]
|
|
||||||
// connection.receivers.forEach { $0.setRtcFrameDecryptor(decryptor) }
|
|
||||||
}
|
}
|
||||||
return Call(
|
return Call(
|
||||||
connection: connection,
|
connection: connection,
|
||||||
iceCandidates: IceCandidates(),
|
iceCandidates: IceCandidates(),
|
||||||
localMedia: mediaType,
|
|
||||||
localCamera: localCamera,
|
localCamera: localCamera,
|
||||||
localVideoSource: localVideoSource,
|
localAudioTrack: localAudioTrack,
|
||||||
localStream: localStream,
|
localVideoTrack: localVideoTrack,
|
||||||
remoteStream: remoteStream,
|
device: device,
|
||||||
aesKey: aesKey,
|
aesKey: aesKey,
|
||||||
frameEncryptor: frameEncryptor,
|
frameEncryptor: frameEncryptor,
|
||||||
frameDecryptor: frameDecryptor
|
frameDecryptor: frameDecryptor,
|
||||||
|
peerHasOldVersion: false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,18 +169,24 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
|
|
||||||
func sendCallCommand(command: WCallCommand) async {
|
func sendCallCommand(command: WCallCommand) async {
|
||||||
var resp: WCallResponse? = nil
|
var resp: WCallResponse? = nil
|
||||||
let pc = activeCall.wrappedValue?.connection
|
let pc = activeCall?.connection
|
||||||
switch command {
|
switch command {
|
||||||
case .capabilities:
|
case let .capabilities(media): // outgoing
|
||||||
|
let localCameraAndTrack: (RTCVideoCapturer, RTCVideoTrack)? = media == .video
|
||||||
|
? createVideoTrackAndStartCapture(.front)
|
||||||
|
: nil
|
||||||
|
notConnectedCall = NotConnectedCall(audioTrack: createAudioTrack(), localCameraAndTrack: localCameraAndTrack, device: .front)
|
||||||
resp = .capabilities(capabilities: CallCapabilities(encryption: WebRTCClient.enableEncryption))
|
resp = .capabilities(capabilities: CallCapabilities(encryption: WebRTCClient.enableEncryption))
|
||||||
case let .start(media: media, aesKey, iceServers, relay):
|
case let .start(media: media, aesKey, iceServers, relay): // incoming
|
||||||
logger.debug("starting incoming call - create webrtc session")
|
logger.debug("starting incoming call - create webrtc session")
|
||||||
if activeCall.wrappedValue != nil { endCall() }
|
if activeCall != nil { endCall() }
|
||||||
let encryption = WebRTCClient.enableEncryption
|
let encryption = WebRTCClient.enableEncryption
|
||||||
let call = initializeCall(iceServers?.toWebRTCIceServers(), media, encryption ? aesKey : nil, relay)
|
let call = initializeCall(iceServers?.toWebRTCIceServers(), media, encryption ? aesKey : nil, relay)
|
||||||
activeCall.wrappedValue = call
|
activeCall = call
|
||||||
|
setupLocalTracks(true, call)
|
||||||
let (offer, error) = await call.connection.offer()
|
let (offer, error) = await call.connection.offer()
|
||||||
if let offer = offer {
|
if let offer = offer {
|
||||||
|
setupEncryptionForLocalTracks(call)
|
||||||
resp = .offer(
|
resp = .offer(
|
||||||
offer: compressToBase64(input: encodeJSON(CustomRTCSessionDescription(type: offer.type.toSdpType(), sdp: offer.sdp))),
|
offer: compressToBase64(input: encodeJSON(CustomRTCSessionDescription(type: offer.type.toSdpType(), sdp: offer.sdp))),
|
||||||
iceCandidates: compressToBase64(input: encodeJSON(await self.getInitialIceCandidates())),
|
iceCandidates: compressToBase64(input: encodeJSON(await self.getInitialIceCandidates())),
|
||||||
@@ -172,18 +196,24 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
} else {
|
} else {
|
||||||
resp = .error(message: "offer error: \(error?.localizedDescription ?? "unknown error")")
|
resp = .error(message: "offer error: \(error?.localizedDescription ?? "unknown error")")
|
||||||
}
|
}
|
||||||
case let .offer(offer, iceCandidates, media, aesKey, iceServers, relay):
|
case let .offer(offer, iceCandidates, media, aesKey, iceServers, relay): // outgoing
|
||||||
if activeCall.wrappedValue != nil {
|
if activeCall != nil {
|
||||||
resp = .error(message: "accept: call already started")
|
resp = .error(message: "accept: call already started")
|
||||||
} else if !WebRTCClient.enableEncryption && aesKey != nil {
|
} else if !WebRTCClient.enableEncryption && aesKey != nil {
|
||||||
resp = .error(message: "accept: encryption is not supported")
|
resp = .error(message: "accept: encryption is not supported")
|
||||||
} else if let offer: CustomRTCSessionDescription = decodeJSON(decompressFromBase64(input: offer)),
|
} else if let offer: CustomRTCSessionDescription = decodeJSON(decompressFromBase64(input: offer)),
|
||||||
let remoteIceCandidates: [RTCIceCandidate] = decodeJSON(decompressFromBase64(input: iceCandidates)) {
|
let remoteIceCandidates: [RTCIceCandidate] = decodeJSON(decompressFromBase64(input: iceCandidates)) {
|
||||||
let call = initializeCall(iceServers?.toWebRTCIceServers(), media, WebRTCClient.enableEncryption ? aesKey : nil, relay)
|
let call = initializeCall(iceServers?.toWebRTCIceServers(), media, WebRTCClient.enableEncryption ? aesKey : nil, relay)
|
||||||
activeCall.wrappedValue = call
|
activeCall = call
|
||||||
let pc = call.connection
|
let pc = call.connection
|
||||||
if let type = offer.type, let sdp = offer.sdp {
|
if let type = offer.type, let sdp = offer.sdp {
|
||||||
if (try? await pc.setRemoteDescription(RTCSessionDescription(type: type.toWebRTCSdpType(), sdp: sdp))) != nil {
|
if (try? await pc.setRemoteDescription(RTCSessionDescription(type: type.toWebRTCSdpType(), sdp: sdp))) != nil {
|
||||||
|
setupLocalTracks(false, call)
|
||||||
|
setupEncryptionForLocalTracks(call)
|
||||||
|
pc.transceivers.forEach { transceiver in
|
||||||
|
transceiver.setDirection(.sendRecv, error: nil)
|
||||||
|
}
|
||||||
|
await adaptToOldVersion(pc.transceivers.count <= 2)
|
||||||
let (answer, error) = await pc.answer()
|
let (answer, error) = await pc.answer()
|
||||||
if let answer = answer {
|
if let answer = answer {
|
||||||
self.addIceCandidates(pc, remoteIceCandidates)
|
self.addIceCandidates(pc, remoteIceCandidates)
|
||||||
@@ -200,7 +230,7 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case let .answer(answer, iceCandidates):
|
case let .answer(answer, iceCandidates): // incoming
|
||||||
if pc == nil {
|
if pc == nil {
|
||||||
resp = .error(message: "answer: call not started")
|
resp = .error(message: "answer: call not started")
|
||||||
} else if pc?.localDescription == nil {
|
} else if pc?.localDescription == nil {
|
||||||
@@ -212,6 +242,9 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
let type = answer.type, let sdp = answer.sdp,
|
let type = answer.type, let sdp = answer.sdp,
|
||||||
let pc = pc {
|
let pc = pc {
|
||||||
if (try? await pc.setRemoteDescription(RTCSessionDescription(type: type.toWebRTCSdpType(), sdp: sdp))) != nil {
|
if (try? await pc.setRemoteDescription(RTCSessionDescription(type: type.toWebRTCSdpType(), sdp: sdp))) != nil {
|
||||||
|
var currentDirection: RTCRtpTransceiverDirection = .sendOnly
|
||||||
|
pc.transceivers[2].currentDirection(¤tDirection)
|
||||||
|
await adaptToOldVersion(currentDirection == .sendOnly)
|
||||||
addIceCandidates(pc, remoteIceCandidates)
|
addIceCandidates(pc, remoteIceCandidates)
|
||||||
resp = .ok
|
resp = .ok
|
||||||
} else {
|
} else {
|
||||||
@@ -226,13 +259,11 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
} else {
|
} else {
|
||||||
resp = .error(message: "ice: call not started")
|
resp = .error(message: "ice: call not started")
|
||||||
}
|
}
|
||||||
case let .media(media, enable):
|
case let .media(source, enable):
|
||||||
if activeCall.wrappedValue == nil {
|
if activeCall == nil {
|
||||||
resp = .error(message: "media: call not started")
|
resp = .error(message: "media: call not started")
|
||||||
} else if activeCall.wrappedValue?.localMedia == .audio && media == .video {
|
|
||||||
resp = .error(message: "media: no video")
|
|
||||||
} else {
|
} else {
|
||||||
enableMedia(media, enable)
|
await enableMedia(source, enable)
|
||||||
resp = .ok
|
resp = .ok
|
||||||
}
|
}
|
||||||
case .end:
|
case .end:
|
||||||
@@ -247,7 +278,7 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
|
|
||||||
func getInitialIceCandidates() async -> [RTCIceCandidate] {
|
func getInitialIceCandidates() async -> [RTCIceCandidate] {
|
||||||
await untilIceComplete(timeoutMs: 750, stepMs: 150) {}
|
await untilIceComplete(timeoutMs: 750, stepMs: 150) {}
|
||||||
let candidates = await activeCall.wrappedValue?.iceCandidates.getAndClear() ?? []
|
let candidates = await activeCall?.iceCandidates.getAndClear() ?? []
|
||||||
logger.debug("WebRTCClient: sending initial ice candidates: \(candidates.count)")
|
logger.debug("WebRTCClient: sending initial ice candidates: \(candidates.count)")
|
||||||
return candidates
|
return candidates
|
||||||
}
|
}
|
||||||
@@ -255,7 +286,7 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
func waitForMoreIceCandidates() {
|
func waitForMoreIceCandidates() {
|
||||||
Task {
|
Task {
|
||||||
await untilIceComplete(timeoutMs: 12000, stepMs: 1500) {
|
await untilIceComplete(timeoutMs: 12000, stepMs: 1500) {
|
||||||
let candidates = await self.activeCall.wrappedValue?.iceCandidates.getAndClear() ?? []
|
let candidates = await self.activeCall?.iceCandidates.getAndClear() ?? []
|
||||||
if candidates.count > 0 {
|
if candidates.count > 0 {
|
||||||
logger.debug("WebRTCClient: sending more ice candidates: \(candidates.count)")
|
logger.debug("WebRTCClient: sending more ice candidates: \(candidates.count)")
|
||||||
await self.sendIceCandidates(candidates)
|
await self.sendIceCandidates(candidates)
|
||||||
@@ -272,25 +303,202 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func enableMedia(_ media: CallMediaType, _ enable: Bool) {
|
func setupMuteUnmuteListener(_ transceiver: RTCRtpTransceiver, _ track: RTCMediaStreamTrack) {
|
||||||
logger.debug("WebRTCClient: enabling media \(media.rawValue) \(enable)")
|
// logger.log("Setting up mute/unmute listener in the call without encryption for mid = \(transceiver.mid)")
|
||||||
media == .video ? setVideoEnabled(enable) : setAudioEnabled(enable)
|
Task {
|
||||||
|
var lastBytesReceived: Int64 = 0
|
||||||
|
// muted initially
|
||||||
|
var mutedSeconds = 4
|
||||||
|
while let call = self.activeCall, transceiver.receiver.track?.readyState == .live {
|
||||||
|
let stats: RTCStatisticsReport = await call.connection.statistics(for: transceiver.receiver)
|
||||||
|
let stat = stats.statistics.values.first(where: { stat in stat.type == "inbound-rtp"})
|
||||||
|
if let stat {
|
||||||
|
//logger.debug("Stat \(stat.debugDescription)")
|
||||||
|
let bytes = stat.values["bytesReceived"] as! Int64
|
||||||
|
if bytes <= lastBytesReceived {
|
||||||
|
mutedSeconds += 1
|
||||||
|
if mutedSeconds == 3 {
|
||||||
|
await MainActor.run {
|
||||||
|
self.onMediaMuteUnmute(transceiver.mid, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if mutedSeconds >= 3 {
|
||||||
|
await MainActor.run {
|
||||||
|
self.onMediaMuteUnmute(transceiver.mid, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastBytesReceived = bytes
|
||||||
|
mutedSeconds = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try? await Task.sleep(nanoseconds: 1000_000000)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addLocalRenderer(_ activeCall: Call, _ renderer: RTCEAGLVideoView) {
|
@MainActor
|
||||||
activeCall.localStream?.add(renderer)
|
func onMediaMuteUnmute(_ transceiverMid: String?, _ mute: Bool) {
|
||||||
|
guard let activeCall = ChatModel.shared.activeCall else { return }
|
||||||
|
let source = mediaSourceFromTransceiverMid(transceiverMid)
|
||||||
|
logger.log("Mute/unmute \(source.rawValue) track = \(mute) with mid = \(transceiverMid ?? "nil")")
|
||||||
|
if source == .mic && activeCall.peerMediaSources.mic == mute {
|
||||||
|
activeCall.peerMediaSources.mic = !mute
|
||||||
|
} else if (source == .camera && activeCall.peerMediaSources.camera == mute) {
|
||||||
|
activeCall.peerMediaSources.camera = !mute
|
||||||
|
} else if (source == .screenAudio && activeCall.peerMediaSources.screenAudio == mute) {
|
||||||
|
activeCall.peerMediaSources.screenAudio = !mute
|
||||||
|
} else if (source == .screenVideo && activeCall.peerMediaSources.screenVideo == mute) {
|
||||||
|
activeCall.peerMediaSources.screenVideo = !mute
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
func enableMedia(_ source: CallMediaSource, _ enable: Bool) {
|
||||||
|
logger.debug("WebRTCClient: enabling media \(source.rawValue) \(enable)")
|
||||||
|
source == .camera ? setCameraEnabled(enable) : setAudioEnabled(enable)
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
func adaptToOldVersion(_ peerHasOldVersion: Bool) {
|
||||||
|
activeCall?.peerHasOldVersion = peerHasOldVersion
|
||||||
|
if peerHasOldVersion {
|
||||||
|
logger.debug("The peer has an old version. Remote audio track is nil = \(self.activeCall?.remoteAudioTrack == nil), video = \(self.activeCall?.remoteVideoTrack == nil)")
|
||||||
|
onMediaMuteUnmute("0", false)
|
||||||
|
if activeCall?.remoteVideoTrack != nil {
|
||||||
|
onMediaMuteUnmute("1", false)
|
||||||
|
}
|
||||||
|
if ChatModel.shared.activeCall?.localMediaSources.camera == true && ChatModel.shared.activeCall?.peerMediaSources.camera == false {
|
||||||
|
logger.debug("Stopping video track for the old version")
|
||||||
|
activeCall?.connection.senders[1].track = nil
|
||||||
|
ChatModel.shared.activeCall?.localMediaSources.camera = false
|
||||||
|
(activeCall?.localCamera as? RTCCameraVideoCapturer)?.stopCapture()
|
||||||
|
activeCall?.localCamera = nil
|
||||||
|
activeCall?.localVideoTrack = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addLocalRenderer(_ renderer: RTCEAGLVideoView) {
|
||||||
|
if let activeCall {
|
||||||
|
if let track = activeCall.localVideoTrack {
|
||||||
|
track.add(renderer)
|
||||||
|
}
|
||||||
|
} else if let notConnectedCall {
|
||||||
|
if let track = notConnectedCall.localCameraAndTrack?.1 {
|
||||||
|
track.add(renderer)
|
||||||
|
}
|
||||||
|
}
|
||||||
// To get width and height of a frame, see videoView(videoView:, didChangeVideoSize)
|
// To get width and height of a frame, see videoView(videoView:, didChangeVideoSize)
|
||||||
renderer.delegate = self
|
renderer.delegate = self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func removeLocalRenderer(_ renderer: RTCEAGLVideoView) {
|
||||||
|
if let activeCall {
|
||||||
|
if let track = activeCall.localVideoTrack {
|
||||||
|
track.remove(renderer)
|
||||||
|
}
|
||||||
|
} else if let notConnectedCall {
|
||||||
|
if let track = notConnectedCall.localCameraAndTrack?.1 {
|
||||||
|
track.remove(renderer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
renderer.delegate = nil
|
||||||
|
}
|
||||||
|
|
||||||
func videoView(_ videoView: RTCVideoRenderer, didChangeVideoSize size: CGSize) {
|
func videoView(_ videoView: RTCVideoRenderer, didChangeVideoSize size: CGSize) {
|
||||||
guard size.height > 0 else { return }
|
guard size.height > 0 else { return }
|
||||||
localRendererAspectRatio.wrappedValue = size.width / size.height
|
localRendererAspectRatio.wrappedValue = size.width / size.height
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupLocalTracks(_ incomingCall: Bool, _ call: Call) {
|
||||||
|
let pc = call.connection
|
||||||
|
let transceivers = call.connection.transceivers
|
||||||
|
let audioTrack = call.localAudioTrack
|
||||||
|
let videoTrack = call.localVideoTrack
|
||||||
|
|
||||||
|
if incomingCall {
|
||||||
|
let micCameraInit = RTCRtpTransceiverInit()
|
||||||
|
// streamIds required for old versions which adds tracks from stream, not from track property
|
||||||
|
micCameraInit.streamIds = ["micCamera"]
|
||||||
|
|
||||||
|
let screenAudioVideoInit = RTCRtpTransceiverInit()
|
||||||
|
screenAudioVideoInit.streamIds = ["screenAudioVideo"]
|
||||||
|
|
||||||
|
// incoming call, no transceivers yet. But they should be added in order: mic, camera, screen audio, screen video
|
||||||
|
// mid = 0, mic
|
||||||
|
if let audioTrack {
|
||||||
|
pc.addTransceiver(with: audioTrack, init: micCameraInit)
|
||||||
|
} else {
|
||||||
|
pc.addTransceiver(of: .audio, init: micCameraInit)
|
||||||
|
}
|
||||||
|
// mid = 1, camera
|
||||||
|
if let videoTrack {
|
||||||
|
pc.addTransceiver(with: videoTrack, init: micCameraInit)
|
||||||
|
} else {
|
||||||
|
pc.addTransceiver(of: .video, init: micCameraInit)
|
||||||
|
}
|
||||||
|
// mid = 2, screenAudio
|
||||||
|
pc.addTransceiver(of: .audio, init: screenAudioVideoInit)
|
||||||
|
// mid = 3, screenVideo
|
||||||
|
pc.addTransceiver(of: .video, init: screenAudioVideoInit)
|
||||||
|
} else {
|
||||||
|
// new version
|
||||||
|
if transceivers.count > 2 {
|
||||||
|
// Outgoing call. All transceivers are ready. Don't addTrack() because it will create new transceivers, replace existing (nil) tracks
|
||||||
|
transceivers
|
||||||
|
.first(where: { elem in mediaSourceFromTransceiverMid(elem.mid) == .mic })?
|
||||||
|
.sender.track = audioTrack
|
||||||
|
transceivers
|
||||||
|
.first(where: { elem in mediaSourceFromTransceiverMid(elem.mid) == .camera })?
|
||||||
|
.sender.track = videoTrack
|
||||||
|
} else {
|
||||||
|
// old version, only two transceivers
|
||||||
|
if let audioTrack {
|
||||||
|
pc.add(audioTrack, streamIds: ["micCamera"])
|
||||||
|
} else {
|
||||||
|
// it's important to have any track in order to be able to turn it on again (currently it's off)
|
||||||
|
let sender = pc.add(createAudioTrack(), streamIds: ["micCamera"])
|
||||||
|
sender?.track = nil
|
||||||
|
}
|
||||||
|
if let videoTrack {
|
||||||
|
pc.add(videoTrack, streamIds: ["micCamera"])
|
||||||
|
} else {
|
||||||
|
// it's important to have any track in order to be able to turn it on again (currently it's off)
|
||||||
|
let localVideoSource = WebRTCClient.factory.videoSource()
|
||||||
|
let localVideoTrack = WebRTCClient.factory.videoTrack(with: localVideoSource, trackId: "video0")
|
||||||
|
let sender = pc.add(localVideoTrack, streamIds: ["micCamera"])
|
||||||
|
sender?.track = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mediaSourceFromTransceiverMid(_ mid: String?) -> CallMediaSource {
|
||||||
|
switch mid {
|
||||||
|
case "0":
|
||||||
|
return .mic
|
||||||
|
case "1":
|
||||||
|
return .camera
|
||||||
|
case "2":
|
||||||
|
return .screenAudio
|
||||||
|
case "3":
|
||||||
|
return .screenVideo
|
||||||
|
default:
|
||||||
|
return .unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should be called after local description set
|
||||||
|
func setupEncryptionForLocalTracks(_ call: Call) {
|
||||||
|
if let encryptor = call.frameEncryptor {
|
||||||
|
call.connection.senders.forEach { $0.setRtcFrameEncryptor(encryptor) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func frameDecryptor(_ decryptor: RTCFrameDecryptor, mediaType: RTCRtpMediaType, withFrame encrypted: Data) -> Data? {
|
func frameDecryptor(_ decryptor: RTCFrameDecryptor, mediaType: RTCRtpMediaType, withFrame encrypted: Data) -> Data? {
|
||||||
guard encrypted.count > 0 else { return nil }
|
guard encrypted.count > 0 else { return nil }
|
||||||
if var key: [CChar] = activeCall.wrappedValue?.aesKey?.cString(using: .utf8),
|
if var key: [CChar] = activeCall?.aesKey?.cString(using: .utf8),
|
||||||
let pointer: UnsafeMutableRawPointer = malloc(encrypted.count) {
|
let pointer: UnsafeMutableRawPointer = malloc(encrypted.count) {
|
||||||
memcpy(pointer, (encrypted as NSData).bytes, encrypted.count)
|
memcpy(pointer, (encrypted as NSData).bytes, encrypted.count)
|
||||||
let isKeyFrame = encrypted[0] & 1 == 0
|
let isKeyFrame = encrypted[0] & 1 == 0
|
||||||
@@ -304,7 +512,7 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
|
|
||||||
func frameEncryptor(_ encryptor: RTCFrameEncryptor, mediaType: RTCRtpMediaType, withFrame unencrypted: Data) -> Data? {
|
func frameEncryptor(_ encryptor: RTCFrameEncryptor, mediaType: RTCRtpMediaType, withFrame unencrypted: Data) -> Data? {
|
||||||
guard unencrypted.count > 0 else { return nil }
|
guard unencrypted.count > 0 else { return nil }
|
||||||
if var key: [CChar] = activeCall.wrappedValue?.aesKey?.cString(using: .utf8),
|
if var key: [CChar] = activeCall?.aesKey?.cString(using: .utf8),
|
||||||
let pointer: UnsafeMutableRawPointer = malloc(unencrypted.count + WebRTCClient.ivTagBytes) {
|
let pointer: UnsafeMutableRawPointer = malloc(unencrypted.count + WebRTCClient.ivTagBytes) {
|
||||||
memcpy(pointer, (unencrypted as NSData).bytes, unencrypted.count)
|
memcpy(pointer, (unencrypted as NSData).bytes, unencrypted.count)
|
||||||
let isKeyFrame = unencrypted[0] & 1 == 0
|
let isKeyFrame = unencrypted[0] & 1 == 0
|
||||||
@@ -327,18 +535,42 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addRemoteRenderer(_ activeCall: Call, _ renderer: RTCVideoRenderer) {
|
func addRemoteCameraRenderer(_ renderer: RTCVideoRenderer) {
|
||||||
activeCall.remoteStream?.add(renderer)
|
if activeCall?.remoteVideoTrack != nil {
|
||||||
|
activeCall?.remoteVideoTrack?.add(renderer)
|
||||||
|
} else {
|
||||||
|
cameraRenderers.append(renderer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeRemoteRenderer(_ activeCall: Call, _ renderer: RTCVideoRenderer) {
|
func removeRemoteCameraRenderer(_ renderer: RTCVideoRenderer) {
|
||||||
activeCall.remoteStream?.remove(renderer)
|
if activeCall?.remoteVideoTrack != nil {
|
||||||
|
activeCall?.remoteVideoTrack?.remove(renderer)
|
||||||
|
} else {
|
||||||
|
cameraRenderers.removeAll(where: { $0.isEqual(renderer) })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func startCaptureLocalVideo(_ activeCall: Call) {
|
func addRemoteScreenRenderer(_ renderer: RTCVideoRenderer) {
|
||||||
|
if activeCall?.remoteScreenVideoTrack != nil {
|
||||||
|
activeCall?.remoteScreenVideoTrack?.add(renderer)
|
||||||
|
} else {
|
||||||
|
screenRenderers.append(renderer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeRemoteScreenRenderer(_ renderer: RTCVideoRenderer) {
|
||||||
|
if activeCall?.remoteScreenVideoTrack != nil {
|
||||||
|
activeCall?.remoteScreenVideoTrack?.remove(renderer)
|
||||||
|
} else {
|
||||||
|
screenRenderers.removeAll(where: { $0.isEqual(renderer) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func startCaptureLocalVideo(_ device: AVCaptureDevice.Position?, _ capturer: RTCVideoCapturer?) {
|
||||||
#if targetEnvironment(simulator)
|
#if targetEnvironment(simulator)
|
||||||
guard
|
guard
|
||||||
let capturer = activeCall.localCamera as? RTCFileVideoCapturer
|
let capturer = (activeCall?.localCamera ?? notConnectedCall?.localCameraAndTrack?.0) as? RTCFileVideoCapturer
|
||||||
else {
|
else {
|
||||||
logger.error("Unable to work with a file capturer")
|
logger.error("Unable to work with a file capturer")
|
||||||
return
|
return
|
||||||
@@ -348,10 +580,10 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
capturer.startCapturing(fromFileNamed: "sounds/video.mp4")
|
capturer.startCapturing(fromFileNamed: "sounds/video.mp4")
|
||||||
#else
|
#else
|
||||||
guard
|
guard
|
||||||
let capturer = activeCall.localCamera as? RTCCameraVideoCapturer,
|
let capturer = capturer as? RTCCameraVideoCapturer,
|
||||||
let camera = (RTCCameraVideoCapturer.captureDevices().first { $0.position == activeCall.device })
|
let camera = (RTCCameraVideoCapturer.captureDevices().first { $0.position == device })
|
||||||
else {
|
else {
|
||||||
logger.error("Unable to find a camera")
|
logger.error("Unable to find a camera or local track")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,19 +609,6 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createAudioSender(_ connection: RTCPeerConnection) {
|
|
||||||
let streamId = "stream"
|
|
||||||
let audioTrack = createAudioTrack()
|
|
||||||
connection.add(audioTrack, streamIds: [streamId])
|
|
||||||
}
|
|
||||||
|
|
||||||
private func createVideoSender(_ connection: RTCPeerConnection) -> (RTCVideoTrack?, RTCVideoTrack?, RTCVideoCapturer?, RTCVideoSource?) {
|
|
||||||
let streamId = "stream"
|
|
||||||
let (localVideoTrack, localCamera, localVideoSource) = createVideoTrack()
|
|
||||||
connection.add(localVideoTrack, streamIds: [streamId])
|
|
||||||
return (localVideoTrack, connection.transceivers.first { $0.mediaType == .video }?.receiver.track as? RTCVideoTrack, localCamera, localVideoSource)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func createAudioTrack() -> RTCAudioTrack {
|
private func createAudioTrack() -> RTCAudioTrack {
|
||||||
let audioConstrains = RTCMediaConstraints(mandatoryConstraints: nil, optionalConstraints: nil)
|
let audioConstrains = RTCMediaConstraints(mandatoryConstraints: nil, optionalConstraints: nil)
|
||||||
let audioSource = WebRTCClient.factory.audioSource(with: audioConstrains)
|
let audioSource = WebRTCClient.factory.audioSource(with: audioConstrains)
|
||||||
@@ -397,7 +616,7 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
return audioTrack
|
return audioTrack
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createVideoTrack() -> (RTCVideoTrack, RTCVideoCapturer, RTCVideoSource) {
|
private func createVideoTrackAndStartCapture(_ device: AVCaptureDevice.Position) -> (RTCVideoCapturer, RTCVideoTrack) {
|
||||||
let localVideoSource = WebRTCClient.factory.videoSource()
|
let localVideoSource = WebRTCClient.factory.videoSource()
|
||||||
|
|
||||||
#if targetEnvironment(simulator)
|
#if targetEnvironment(simulator)
|
||||||
@@ -407,7 +626,8 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
let localVideoTrack = WebRTCClient.factory.videoTrack(with: localVideoSource, trackId: "video0")
|
let localVideoTrack = WebRTCClient.factory.videoTrack(with: localVideoSource, trackId: "video0")
|
||||||
return (localVideoTrack, localCamera, localVideoSource)
|
startCaptureLocalVideo(device, localCamera)
|
||||||
|
return (localCamera, localVideoTrack)
|
||||||
}
|
}
|
||||||
|
|
||||||
func endCall() {
|
func endCall() {
|
||||||
@@ -420,15 +640,16 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func _endCall() {
|
private func _endCall() {
|
||||||
guard let call = activeCall.wrappedValue else { return }
|
(notConnectedCall?.localCameraAndTrack?.0 as? RTCCameraVideoCapturer)?.stopCapture()
|
||||||
|
guard let call = activeCall else { return }
|
||||||
logger.debug("WebRTCClient: ending the call")
|
logger.debug("WebRTCClient: ending the call")
|
||||||
activeCall.wrappedValue = nil
|
|
||||||
(call.localCamera as? RTCCameraVideoCapturer)?.stopCapture()
|
|
||||||
call.connection.close()
|
call.connection.close()
|
||||||
call.connection.delegate = nil
|
call.connection.delegate = nil
|
||||||
call.frameEncryptor?.delegate = nil
|
call.frameEncryptor?.delegate = nil
|
||||||
call.frameDecryptor?.delegate = nil
|
call.frameDecryptor?.delegate = nil
|
||||||
|
(call.localCamera as? RTCCameraVideoCapturer)?.stopCapture()
|
||||||
audioSessionToDefaults()
|
audioSessionToDefaults()
|
||||||
|
activeCall = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func untilIceComplete(timeoutMs: UInt64, stepMs: UInt64, action: @escaping () async -> Void) async {
|
func untilIceComplete(timeoutMs: UInt64, stepMs: UInt64, action: @escaping () async -> Void) async {
|
||||||
@@ -437,7 +658,7 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
|
|||||||
_ = try? await Task.sleep(nanoseconds: stepMs * 1000000)
|
_ = try? await Task.sleep(nanoseconds: stepMs * 1000000)
|
||||||
t += stepMs
|
t += stepMs
|
||||||
await action()
|
await action()
|
||||||
} while t < timeoutMs && activeCall.wrappedValue?.connection.iceGatheringState != .complete
|
} while t < timeoutMs && activeCall?.connection.iceGatheringState != .complete
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,11 +719,40 @@ extension WebRTCClient: RTCPeerConnectionDelegate {
|
|||||||
logger.debug("Connection should negotiate")
|
logger.debug("Connection should negotiate")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func peerConnection(_ peerConnection: RTCPeerConnection, didStartReceivingOn transceiver: RTCRtpTransceiver) {
|
||||||
|
if let track = transceiver.receiver.track {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
// Doesn't work for outgoing video call (audio in video call works ok still, same as incoming call)
|
||||||
|
// if let decryptor = self.activeCall?.frameDecryptor {
|
||||||
|
// transceiver.receiver.setRtcFrameDecryptor(decryptor)
|
||||||
|
// }
|
||||||
|
let source = self.mediaSourceFromTransceiverMid(transceiver.mid)
|
||||||
|
switch source {
|
||||||
|
case .mic: self.activeCall?.remoteAudioTrack = track as? RTCAudioTrack
|
||||||
|
case .camera:
|
||||||
|
self.activeCall?.remoteVideoTrack = track as? RTCVideoTrack
|
||||||
|
self.cameraRenderers.forEach({ renderer in
|
||||||
|
self.activeCall?.remoteVideoTrack?.add(renderer)
|
||||||
|
})
|
||||||
|
self.cameraRenderers.removeAll()
|
||||||
|
case .screenAudio: self.activeCall?.remoteScreenAudioTrack = track as? RTCAudioTrack
|
||||||
|
case .screenVideo:
|
||||||
|
self.activeCall?.remoteScreenVideoTrack = track as? RTCVideoTrack
|
||||||
|
self.screenRenderers.forEach({ renderer in
|
||||||
|
self.activeCall?.remoteScreenVideoTrack?.add(renderer)
|
||||||
|
})
|
||||||
|
self.screenRenderers.removeAll()
|
||||||
|
case .unknown: ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.setupMuteUnmuteListener(transceiver, track)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func peerConnection(_ connection: RTCPeerConnection, didChange newState: RTCIceConnectionState) {
|
func peerConnection(_ connection: RTCPeerConnection, didChange newState: RTCIceConnectionState) {
|
||||||
debugPrint("Connection new connection state: \(newState.toString() ?? "" + newState.rawValue.description) \(connection.receivers)")
|
debugPrint("Connection new connection state: \(newState.toString() ?? "" + newState.rawValue.description) \(connection.receivers)")
|
||||||
|
|
||||||
guard let call = activeCall.wrappedValue,
|
guard let connectionStateString = newState.toString(),
|
||||||
let connectionStateString = newState.toString(),
|
|
||||||
let iceConnectionStateString = connection.iceConnectionState.toString(),
|
let iceConnectionStateString = connection.iceConnectionState.toString(),
|
||||||
let iceGatheringStateString = connection.iceGatheringState.toString(),
|
let iceGatheringStateString = connection.iceGatheringState.toString(),
|
||||||
let signalingStateString = connection.signalingState.toString()
|
let signalingStateString = connection.signalingState.toString()
|
||||||
@@ -523,18 +773,14 @@ extension WebRTCClient: RTCPeerConnectionDelegate {
|
|||||||
|
|
||||||
switch newState {
|
switch newState {
|
||||||
case .checking:
|
case .checking:
|
||||||
if let frameDecryptor = activeCall.wrappedValue?.frameDecryptor {
|
if let frameDecryptor = activeCall?.frameDecryptor {
|
||||||
connection.receivers.forEach { $0.setRtcFrameDecryptor(frameDecryptor) }
|
connection.receivers.forEach { $0.setRtcFrameDecryptor(frameDecryptor) }
|
||||||
}
|
}
|
||||||
let enableSpeaker: Bool
|
let enableSpeaker: Bool = ChatModel.shared.activeCall?.localMediaSources.hasVideo == true
|
||||||
switch call.localMedia {
|
|
||||||
case .video: enableSpeaker = true
|
|
||||||
default: enableSpeaker = false
|
|
||||||
}
|
|
||||||
setSpeakerEnabledAndConfigureSession(enableSpeaker)
|
setSpeakerEnabledAndConfigureSession(enableSpeaker)
|
||||||
case .connected: sendConnectedEvent(connection)
|
case .connected: sendConnectedEvent(connection)
|
||||||
case .disconnected, .failed: endCall()
|
case .disconnected, .failed: endCall()
|
||||||
default: do {}
|
default: ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -546,7 +792,7 @@ extension WebRTCClient: RTCPeerConnectionDelegate {
|
|||||||
func peerConnection(_ connection: RTCPeerConnection, didGenerate candidate: WebRTC.RTCIceCandidate) {
|
func peerConnection(_ connection: RTCPeerConnection, didGenerate candidate: WebRTC.RTCIceCandidate) {
|
||||||
// logger.debug("Connection generated candidate \(candidate.debugDescription)")
|
// logger.debug("Connection generated candidate \(candidate.debugDescription)")
|
||||||
Task {
|
Task {
|
||||||
await self.activeCall.wrappedValue?.iceCandidates.append(candidate.toCandidate(nil, nil))
|
await self.activeCall?.iceCandidates.append(candidate.toCandidate(nil, nil))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -601,11 +847,42 @@ extension WebRTCClient: RTCPeerConnectionDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension WebRTCClient {
|
extension WebRTCClient {
|
||||||
func setAudioEnabled(_ enabled: Bool) {
|
static func isAuthorized(for type: AVMediaType) async -> Bool {
|
||||||
setTrackEnabled(RTCAudioTrack.self, enabled)
|
let status = AVCaptureDevice.authorizationStatus(for: type)
|
||||||
|
var isAuthorized = status == .authorized
|
||||||
|
if status == .notDetermined {
|
||||||
|
isAuthorized = await AVCaptureDevice.requestAccess(for: type)
|
||||||
|
}
|
||||||
|
return isAuthorized
|
||||||
}
|
}
|
||||||
|
|
||||||
func setSpeakerEnabledAndConfigureSession( _ enabled: Bool) {
|
static func showUnauthorizedAlert(for type: AVMediaType) {
|
||||||
|
if type == .audio {
|
||||||
|
AlertManager.shared.showAlert(Alert(
|
||||||
|
title: Text("No permission to record speech"),
|
||||||
|
message: Text("To record speech please grant permission to use Microphone."),
|
||||||
|
primaryButton: .default(Text("Open Settings")) {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
secondaryButton: .cancel()
|
||||||
|
))
|
||||||
|
} else if type == .video {
|
||||||
|
AlertManager.shared.showAlert(Alert(
|
||||||
|
title: Text("No permission to record video"),
|
||||||
|
message: Text("To record video please grant permission to use Camera."),
|
||||||
|
primaryButton: .default(Text("Open Settings")) {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
secondaryButton: .cancel()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setSpeakerEnabledAndConfigureSession( _ enabled: Bool, skipExternalDevice: Bool = false) {
|
||||||
logger.debug("WebRTCClient: configuring session with speaker enabled \(enabled)")
|
logger.debug("WebRTCClient: configuring session with speaker enabled \(enabled)")
|
||||||
audioQueue.async { [weak self] in
|
audioQueue.async { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
@@ -618,7 +895,7 @@ extension WebRTCClient {
|
|||||||
if enabled {
|
if enabled {
|
||||||
try self.rtcAudioSession.setCategory(AVAudioSession.Category.playAndRecord.rawValue, with: [.defaultToSpeaker, .allowBluetooth, .allowAirPlay, .allowBluetoothA2DP])
|
try self.rtcAudioSession.setCategory(AVAudioSession.Category.playAndRecord.rawValue, with: [.defaultToSpeaker, .allowBluetooth, .allowAirPlay, .allowBluetoothA2DP])
|
||||||
try self.rtcAudioSession.setMode(AVAudioSession.Mode.videoChat.rawValue)
|
try self.rtcAudioSession.setMode(AVAudioSession.Mode.videoChat.rawValue)
|
||||||
if hasExternalAudioDevice, let preferred = self.rtcAudioSession.session.preferredInputDevice() {
|
if hasExternalAudioDevice && !skipExternalDevice, let preferred = self.rtcAudioSession.session.preferredInputDevice() {
|
||||||
try self.rtcAudioSession.setPreferredInput(preferred)
|
try self.rtcAudioSession.setPreferredInput(preferred)
|
||||||
} else {
|
} else {
|
||||||
try self.rtcAudioSession.overrideOutputAudioPort(.speaker)
|
try self.rtcAudioSession.overrideOutputAudioPort(.speaker)
|
||||||
@@ -628,7 +905,7 @@ extension WebRTCClient {
|
|||||||
try self.rtcAudioSession.setMode(AVAudioSession.Mode.voiceChat.rawValue)
|
try self.rtcAudioSession.setMode(AVAudioSession.Mode.voiceChat.rawValue)
|
||||||
try self.rtcAudioSession.overrideOutputAudioPort(.none)
|
try self.rtcAudioSession.overrideOutputAudioPort(.none)
|
||||||
}
|
}
|
||||||
if hasExternalAudioDevice {
|
if hasExternalAudioDevice && !skipExternalDevice {
|
||||||
logger.debug("WebRTCClient: configuring session with external device available, skip configuring speaker")
|
logger.debug("WebRTCClient: configuring session with external device available, skip configuring speaker")
|
||||||
}
|
}
|
||||||
try self.rtcAudioSession.setActive(true)
|
try self.rtcAudioSession.setActive(true)
|
||||||
@@ -659,25 +936,59 @@ extension WebRTCClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setVideoEnabled(_ enabled: Bool) {
|
@MainActor
|
||||||
setTrackEnabled(RTCVideoTrack.self, enabled)
|
func setAudioEnabled(_ enabled: Bool) {
|
||||||
|
if activeCall != nil {
|
||||||
|
activeCall?.localAudioTrack = enabled ? createAudioTrack() : nil
|
||||||
|
activeCall?.connection.transceivers.first(where: { t in mediaSourceFromTransceiverMid(t.mid) == .mic })?.sender.track = activeCall?.localAudioTrack
|
||||||
|
} else if notConnectedCall != nil {
|
||||||
|
notConnectedCall?.audioTrack = enabled ? createAudioTrack() : nil
|
||||||
|
}
|
||||||
|
ChatModel.shared.activeCall?.localMediaSources.mic = enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
func setCameraEnabled(_ enabled: Bool) {
|
||||||
|
if let call = activeCall {
|
||||||
|
if enabled {
|
||||||
|
if call.localVideoTrack == nil {
|
||||||
|
let device = activeCall?.device ?? notConnectedCall?.device ?? .front
|
||||||
|
let (camera, track) = createVideoTrackAndStartCapture(device)
|
||||||
|
activeCall?.localCamera = camera
|
||||||
|
activeCall?.localVideoTrack = track
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(call.localCamera as? RTCCameraVideoCapturer)?.stopCapture()
|
||||||
|
activeCall?.localCamera = nil
|
||||||
|
activeCall?.localVideoTrack = nil
|
||||||
|
}
|
||||||
|
call.connection.transceivers
|
||||||
|
.first(where: { t in mediaSourceFromTransceiverMid(t.mid) == .camera })?
|
||||||
|
.sender.track = activeCall?.localVideoTrack
|
||||||
|
ChatModel.shared.activeCall?.localMediaSources.camera = activeCall?.localVideoTrack != nil
|
||||||
|
} else if let call = notConnectedCall {
|
||||||
|
if enabled {
|
||||||
|
let device = activeCall?.device ?? notConnectedCall?.device ?? .front
|
||||||
|
notConnectedCall?.localCameraAndTrack = createVideoTrackAndStartCapture(device)
|
||||||
|
} else {
|
||||||
|
(call.localCameraAndTrack?.0 as? RTCCameraVideoCapturer)?.stopCapture()
|
||||||
|
notConnectedCall?.localCameraAndTrack = nil
|
||||||
|
}
|
||||||
|
ChatModel.shared.activeCall?.localMediaSources.camera = notConnectedCall?.localCameraAndTrack != nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func flipCamera() {
|
func flipCamera() {
|
||||||
switch activeCall.wrappedValue?.device {
|
let device = activeCall?.device ?? notConnectedCall?.device
|
||||||
case .front: activeCall.wrappedValue?.device = .back
|
if activeCall != nil {
|
||||||
case .back: activeCall.wrappedValue?.device = .front
|
activeCall?.device = device == .front ? .back : .front
|
||||||
default: ()
|
} else {
|
||||||
|
notConnectedCall?.device = device == .front ? .back : .front
|
||||||
}
|
}
|
||||||
if let call = activeCall.wrappedValue {
|
startCaptureLocalVideo(
|
||||||
startCaptureLocalVideo(call)
|
activeCall?.device ?? notConnectedCall?.device,
|
||||||
}
|
(activeCall?.localCamera ?? notConnectedCall?.localCameraAndTrack?.0) as? RTCCameraVideoCapturer
|
||||||
}
|
)
|
||||||
|
|
||||||
private func setTrackEnabled<T: RTCMediaStreamTrack>(_ type: T.Type, _ enabled: Bool) {
|
|
||||||
activeCall.wrappedValue?.connection.transceivers
|
|
||||||
.compactMap { $0.sender.track as? T }
|
|
||||||
.forEach { $0.isEnabled = enabled }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import SimpleXChat
|
|||||||
|
|
||||||
struct CIChatFeatureView: View {
|
struct CIChatFeatureView: View {
|
||||||
@EnvironmentObject var m: ChatModel
|
@EnvironmentObject var m: ChatModel
|
||||||
|
@Environment(\.revealed) var revealed: Bool
|
||||||
@ObservedObject var im = ItemsModel.shared
|
@ObservedObject var im = ItemsModel.shared
|
||||||
@ObservedObject var chat: Chat
|
@ObservedObject var chat: Chat
|
||||||
@EnvironmentObject var theme: AppTheme
|
@EnvironmentObject var theme: AppTheme
|
||||||
var chatItem: ChatItem
|
var chatItem: ChatItem
|
||||||
@Binding var revealed: Bool
|
|
||||||
var feature: Feature
|
var feature: Feature
|
||||||
var icon: String? = nil
|
var icon: String? = nil
|
||||||
var iconColor: Color
|
var iconColor: Color
|
||||||
@@ -106,6 +106,9 @@ struct CIChatFeatureView: View {
|
|||||||
struct CIChatFeatureView_Previews: PreviewProvider {
|
struct CIChatFeatureView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let enabled = FeatureEnabled(forUser: false, forContact: false)
|
let enabled = FeatureEnabled(forUser: false, forContact: false)
|
||||||
CIChatFeatureView(chat: Chat.sampleData, chatItem: ChatItem.getChatFeatureSample(.fullDelete, enabled), revealed: Binding.constant(true), feature: ChatFeature.fullDelete, iconColor: enabled.iconColor(.secondary))
|
CIChatFeatureView(
|
||||||
|
chat: Chat.sampleData,
|
||||||
|
chatItem: ChatItem.getChatFeatureSample(.fullDelete, enabled), feature: ChatFeature.fullDelete, iconColor: enabled.iconColor(.secondary)
|
||||||
|
).environment(\.revealed, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,17 +285,18 @@ struct CIFileView_Previews: PreviewProvider {
|
|||||||
file: nil
|
file: nil
|
||||||
)
|
)
|
||||||
Group {
|
Group {
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: sentFile, revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: sentFile)
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample())
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileName: "some_long_file_name_here", fileStatus: .rcvInvitation), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileName: "some_long_file_name_here", fileStatus: .rcvInvitation))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvAccepted), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvAccepted))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvCancelled), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvCancelled))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileSize: 1_000_000_000, fileStatus: .rcvInvitation), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileSize: 1_000_000_000, fileStatus: .rcvInvitation))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(text: "Hello there", fileStatus: .rcvInvitation), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(text: "Hello there", fileStatus: .rcvInvitation))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", fileStatus: .rcvInvitation), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", fileStatus: .rcvInvitation))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: fileChatItemWtFile, revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: fileChatItemWtFile)
|
||||||
}
|
}
|
||||||
|
.environment(\.revealed, false)
|
||||||
.previewLayout(.fixed(width: 360, height: 360))
|
.previewLayout(.fixed(width: 360, height: 360))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ struct CIRcvDecryptionError: View {
|
|||||||
if case let .group(groupInfo) = chat.chatInfo,
|
if case let .group(groupInfo) = chat.chatInfo,
|
||||||
case let .groupRcv(groupMember) = chatItem.chatDir {
|
case let .groupRcv(groupMember) = chatItem.chatDir {
|
||||||
do {
|
do {
|
||||||
let (member, stats) = try apiGroupMemberInfo(groupInfo.apiId, groupMember.groupMemberId)
|
let (member, stats) = try apiGroupMemberInfoSync(groupInfo.apiId, groupMember.groupMemberId)
|
||||||
if let s = stats {
|
if let s = stats {
|
||||||
m.updateGroupMemberConnectionStats(groupInfo, member, s)
|
m.updateGroupMemberConnectionStats(groupInfo, member, s)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -510,10 +510,10 @@ struct CIVoiceView_Previews: PreviewProvider {
|
|||||||
duration: 30,
|
duration: 30,
|
||||||
allowMenu: Binding.constant(true)
|
allowMenu: Binding.constant(true)
|
||||||
)
|
)
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: sentVoiceMessage, revealed: Binding.constant(false), allowMenu: .constant(true))
|
ChatItemView(chat: Chat.sampleData, chatItem: sentVoiceMessage, allowMenu: .constant(true))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(), revealed: Binding.constant(false), allowMenu: .constant(true))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(), allowMenu: .constant(true))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)), revealed: Binding.constant(false), allowMenu: .constant(true))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)), allowMenu: .constant(true))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: voiceMessageWtFile, revealed: Binding.constant(false), allowMenu: .constant(true))
|
ChatItemView(chat: Chat.sampleData, chatItem: voiceMessageWtFile, allowMenu: .constant(true))
|
||||||
}
|
}
|
||||||
.previewLayout(.fixed(width: 360, height: 360))
|
.previewLayout(.fixed(width: 360, height: 360))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,12 +92,13 @@ struct FramedCIVoiceView_Previews: PreviewProvider {
|
|||||||
file: CIFile.getSample(fileStatus: .sndComplete)
|
file: CIFile.getSample(fileStatus: .sndComplete)
|
||||||
)
|
)
|
||||||
Group {
|
Group {
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: sentVoiceMessage, revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: sentVoiceMessage)
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Hello there"), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Hello there"))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Hello there", fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Hello there", fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: voiceMessageWithQuote, revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: voiceMessageWithQuote)
|
||||||
}
|
}
|
||||||
|
.environment(\.revealed, false)
|
||||||
.previewLayout(.fixed(width: 360, height: 360))
|
.previewLayout(.fixed(width: 360, height: 360))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -12,9 +12,9 @@ import SimpleXChat
|
|||||||
struct MarkedDeletedItemView: View {
|
struct MarkedDeletedItemView: View {
|
||||||
@EnvironmentObject var m: ChatModel
|
@EnvironmentObject var m: ChatModel
|
||||||
@EnvironmentObject var theme: AppTheme
|
@EnvironmentObject var theme: AppTheme
|
||||||
|
@Environment(\.revealed) var revealed: Bool
|
||||||
@ObservedObject var chat: Chat
|
@ObservedObject var chat: Chat
|
||||||
var chatItem: ChatItem
|
var chatItem: ChatItem
|
||||||
@Binding var revealed: Bool
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
(Text(mergedMarkedDeletedText).italic() + Text(" ") + chatItem.timestampText)
|
(Text(mergedMarkedDeletedText).italic() + Text(" ") + chatItem.timestampText)
|
||||||
@@ -79,7 +79,10 @@ struct MarkedDeletedItemView: View {
|
|||||||
struct MarkedDeletedItemView_Previews: PreviewProvider {
|
struct MarkedDeletedItemView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
Group {
|
Group {
|
||||||
MarkedDeletedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(true))
|
MarkedDeletedItemView(
|
||||||
|
chat: Chat.sampleData,
|
||||||
|
chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now))
|
||||||
|
).environment(\.revealed, true)
|
||||||
}
|
}
|
||||||
.previewLayout(.fixed(width: 360, height: 200))
|
.previewLayout(.fixed(width: 360, height: 200))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,19 +14,28 @@ extension EnvironmentValues {
|
|||||||
static let defaultValue: Bool = true
|
static let defaultValue: Bool = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Revealed: EnvironmentKey {
|
||||||
|
static let defaultValue: Bool = true
|
||||||
|
}
|
||||||
|
|
||||||
var showTimestamp: Bool {
|
var showTimestamp: Bool {
|
||||||
get { self[ShowTimestamp.self] }
|
get { self[ShowTimestamp.self] }
|
||||||
set { self[ShowTimestamp.self] = newValue }
|
set { self[ShowTimestamp.self] = newValue }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var revealed: Bool {
|
||||||
|
get { self[Revealed.self] }
|
||||||
|
set { self[Revealed.self] = newValue }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ChatItemView: View {
|
struct ChatItemView: View {
|
||||||
@ObservedObject var chat: Chat
|
@ObservedObject var chat: Chat
|
||||||
@EnvironmentObject var theme: AppTheme
|
@EnvironmentObject var theme: AppTheme
|
||||||
@Environment(\.showTimestamp) var showTimestamp: Bool
|
@Environment(\.showTimestamp) var showTimestamp: Bool
|
||||||
|
@Environment(\.revealed) var revealed: Bool
|
||||||
var chatItem: ChatItem
|
var chatItem: ChatItem
|
||||||
var maxWidth: CGFloat = .infinity
|
var maxWidth: CGFloat = .infinity
|
||||||
@Binding var revealed: Bool
|
|
||||||
@Binding var allowMenu: Bool
|
@Binding var allowMenu: Bool
|
||||||
|
|
||||||
init(
|
init(
|
||||||
@@ -34,27 +43,25 @@ struct ChatItemView: View {
|
|||||||
chatItem: ChatItem,
|
chatItem: ChatItem,
|
||||||
showMember: Bool = false,
|
showMember: Bool = false,
|
||||||
maxWidth: CGFloat = .infinity,
|
maxWidth: CGFloat = .infinity,
|
||||||
revealed: Binding<Bool>,
|
|
||||||
allowMenu: Binding<Bool> = .constant(false)
|
allowMenu: Binding<Bool> = .constant(false)
|
||||||
) {
|
) {
|
||||||
self.chat = chat
|
self.chat = chat
|
||||||
self.chatItem = chatItem
|
self.chatItem = chatItem
|
||||||
self.maxWidth = maxWidth
|
self.maxWidth = maxWidth
|
||||||
_revealed = revealed
|
|
||||||
_allowMenu = allowMenu
|
_allowMenu = allowMenu
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let ci = chatItem
|
let ci = chatItem
|
||||||
if chatItem.meta.itemDeleted != nil && (!revealed || chatItem.isDeletedContent) {
|
if chatItem.meta.itemDeleted != nil && (!revealed || chatItem.isDeletedContent) {
|
||||||
MarkedDeletedItemView(chat: chat, chatItem: chatItem, revealed: $revealed)
|
MarkedDeletedItemView(chat: chat, chatItem: chatItem)
|
||||||
} else if ci.quotedItem == nil && ci.meta.itemForwarded == nil && ci.meta.itemDeleted == nil && !ci.meta.isLive {
|
} else if ci.quotedItem == nil && ci.meta.itemForwarded == nil && ci.meta.itemDeleted == nil && !ci.meta.isLive {
|
||||||
if let mc = ci.content.msgContent, mc.isText && isShortEmoji(ci.content.text) {
|
if let mc = ci.content.msgContent, mc.isText && isShortEmoji(ci.content.text) {
|
||||||
EmojiItemView(chat: chat, chatItem: ci)
|
EmojiItemView(chat: chat, chatItem: ci)
|
||||||
} else if ci.content.text.isEmpty, case let .voice(_, duration) = ci.content.msgContent {
|
} else if ci.content.text.isEmpty, case let .voice(_, duration) = ci.content.msgContent {
|
||||||
CIVoiceView(chat: chat, chatItem: ci, recordingFile: ci.file, duration: duration, allowMenu: $allowMenu)
|
CIVoiceView(chat: chat, chatItem: ci, recordingFile: ci.file, duration: duration, allowMenu: $allowMenu)
|
||||||
} else if ci.content.msgContent == nil {
|
} else if ci.content.msgContent == nil {
|
||||||
ChatItemContentView(chat: chat, chatItem: chatItem, revealed: $revealed, msgContentView: { Text(ci.text) }) // msgContent is unreachable branch in this case
|
ChatItemContentView(chat: chat, chatItem: chatItem, msgContentView: { Text(ci.text) }) // msgContent is unreachable branch in this case
|
||||||
} else {
|
} else {
|
||||||
framedItemView()
|
framedItemView()
|
||||||
}
|
}
|
||||||
@@ -84,7 +91,6 @@ struct ChatItemView: View {
|
|||||||
chat: chat,
|
chat: chat,
|
||||||
chatItem: chatItem,
|
chatItem: chatItem,
|
||||||
preview: preview,
|
preview: preview,
|
||||||
revealed: $revealed,
|
|
||||||
maxWidth: maxWidth,
|
maxWidth: maxWidth,
|
||||||
imgWidth: adjustedMaxWidth,
|
imgWidth: adjustedMaxWidth,
|
||||||
videoWidth: adjustedMaxWidth,
|
videoWidth: adjustedMaxWidth,
|
||||||
@@ -96,9 +102,9 @@ struct ChatItemView: View {
|
|||||||
struct ChatItemContentView<Content: View>: View {
|
struct ChatItemContentView<Content: View>: View {
|
||||||
@EnvironmentObject var chatModel: ChatModel
|
@EnvironmentObject var chatModel: ChatModel
|
||||||
@EnvironmentObject var theme: AppTheme
|
@EnvironmentObject var theme: AppTheme
|
||||||
|
@Environment(\.revealed) var revealed: Bool
|
||||||
@ObservedObject var chat: Chat
|
@ObservedObject var chat: Chat
|
||||||
var chatItem: ChatItem
|
var chatItem: ChatItem
|
||||||
@Binding var revealed: Bool
|
|
||||||
var msgContentView: () -> Content
|
var msgContentView: () -> Content
|
||||||
@AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false
|
@AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false
|
||||||
|
|
||||||
@@ -130,7 +136,7 @@ struct ChatItemContentView<Content: View>: View {
|
|||||||
case let .rcvChatPreference(feature, allowed, param):
|
case let .rcvChatPreference(feature, allowed, param):
|
||||||
CIFeaturePreferenceView(chat: chat, chatItem: chatItem, feature: feature, allowed: allowed, param: param)
|
CIFeaturePreferenceView(chat: chat, chatItem: chatItem, feature: feature, allowed: allowed, param: param)
|
||||||
case let .sndChatPreference(feature, _, _):
|
case let .sndChatPreference(feature, _, _):
|
||||||
CIChatFeatureView(chat: chat, chatItem: chatItem, revealed: $revealed, feature: feature, icon: feature.icon, iconColor: theme.colors.secondary)
|
CIChatFeatureView(chat: chat, chatItem: chatItem, feature: feature, icon: feature.icon, iconColor: theme.colors.secondary)
|
||||||
case let .rcvGroupFeature(feature, preference, _, role): chatFeatureView(feature, preference.enabled(role, for: chat.chatInfo.groupInfo?.membership).iconColor(theme.colors.secondary))
|
case let .rcvGroupFeature(feature, preference, _, role): chatFeatureView(feature, preference.enabled(role, for: chat.chatInfo.groupInfo?.membership).iconColor(theme.colors.secondary))
|
||||||
case let .sndGroupFeature(feature, preference, _, role): chatFeatureView(feature, preference.enabled(role, for: chat.chatInfo.groupInfo?.membership).iconColor(theme.colors.secondary))
|
case let .sndGroupFeature(feature, preference, _, role): chatFeatureView(feature, preference.enabled(role, for: chat.chatInfo.groupInfo?.membership).iconColor(theme.colors.secondary))
|
||||||
case let .rcvChatFeatureRejected(feature): chatFeatureView(feature, .red)
|
case let .rcvChatFeatureRejected(feature): chatFeatureView(feature, .red)
|
||||||
@@ -177,7 +183,7 @@ struct ChatItemContentView<Content: View>: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func chatFeatureView(_ feature: Feature, _ iconColor: Color) -> some View {
|
private func chatFeatureView(_ feature: Feature, _ iconColor: Color) -> some View {
|
||||||
CIChatFeatureView(chat: chat, chatItem: chatItem, revealed: $revealed, feature: feature, iconColor: iconColor)
|
CIChatFeatureView(chat: chat, chatItem: chatItem, feature: feature, iconColor: iconColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var mergedGroupEventText: Text? {
|
private var mergedGroupEventText: Text? {
|
||||||
@@ -238,16 +244,17 @@ func chatEventText(_ ci: ChatItem, _ secondaryColor: Color) -> Text {
|
|||||||
struct ChatItemView_Previews: PreviewProvider {
|
struct ChatItemView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
Group{
|
Group{
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello"), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello"))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too"), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too"))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂"), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂"))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂"), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂"))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂🙂"), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂🙂"))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getDeletedContentSample(), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getDeletedContentSample())
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now)))
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂", .sndSent(sndProgress: .complete), itemLive: true), revealed: Binding.constant(true))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂", .sndSent(sndProgress: .complete), itemLive: true)).environment(\.revealed, true)
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemLive: true), revealed: Binding.constant(true))
|
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemLive: true)).environment(\.revealed, true)
|
||||||
}
|
}
|
||||||
|
.environment(\.revealed, false)
|
||||||
.previewLayout(.fixed(width: 360, height: 70))
|
.previewLayout(.fixed(width: 360, height: 70))
|
||||||
.environmentObject(Chat.sampleData)
|
.environmentObject(Chat.sampleData)
|
||||||
}
|
}
|
||||||
@@ -265,8 +272,7 @@ struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider {
|
|||||||
content: .rcvIntegrityError(msgError: .msgSkipped(fromMsgId: 1, toMsgId: 2)),
|
content: .rcvIntegrityError(msgError: .msgSkipped(fromMsgId: 1, toMsgId: 2)),
|
||||||
quotedItem: nil,
|
quotedItem: nil,
|
||||||
file: nil
|
file: nil
|
||||||
),
|
)
|
||||||
revealed: Binding.constant(true)
|
|
||||||
)
|
)
|
||||||
ChatItemView(
|
ChatItemView(
|
||||||
chat: Chat.sampleData,
|
chat: Chat.sampleData,
|
||||||
@@ -276,8 +282,7 @@ struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider {
|
|||||||
content: .rcvDecryptionError(msgDecryptError: .ratchetHeader, msgCount: 2),
|
content: .rcvDecryptionError(msgDecryptError: .ratchetHeader, msgCount: 2),
|
||||||
quotedItem: nil,
|
quotedItem: nil,
|
||||||
file: nil
|
file: nil
|
||||||
),
|
)
|
||||||
revealed: Binding.constant(true)
|
|
||||||
)
|
)
|
||||||
ChatItemView(
|
ChatItemView(
|
||||||
chat: Chat.sampleData,
|
chat: Chat.sampleData,
|
||||||
@@ -287,8 +292,7 @@ struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider {
|
|||||||
content: .rcvGroupInvitation(groupInvitation: CIGroupInvitation.getSample(status: .pending), memberRole: .admin),
|
content: .rcvGroupInvitation(groupInvitation: CIGroupInvitation.getSample(status: .pending), memberRole: .admin),
|
||||||
quotedItem: nil,
|
quotedItem: nil,
|
||||||
file: nil
|
file: nil
|
||||||
),
|
)
|
||||||
revealed: Binding.constant(true)
|
|
||||||
)
|
)
|
||||||
ChatItemView(
|
ChatItemView(
|
||||||
chat: Chat.sampleData,
|
chat: Chat.sampleData,
|
||||||
@@ -298,8 +302,7 @@ struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider {
|
|||||||
content: .rcvGroupEvent(rcvGroupEvent: .memberAdded(groupMemberId: 1, profile: Profile.sampleData)),
|
content: .rcvGroupEvent(rcvGroupEvent: .memberAdded(groupMemberId: 1, profile: Profile.sampleData)),
|
||||||
quotedItem: nil,
|
quotedItem: nil,
|
||||||
file: nil
|
file: nil
|
||||||
),
|
)
|
||||||
revealed: Binding.constant(true)
|
|
||||||
)
|
)
|
||||||
ChatItemView(
|
ChatItemView(
|
||||||
chat: Chat.sampleData,
|
chat: Chat.sampleData,
|
||||||
@@ -309,10 +312,10 @@ struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider {
|
|||||||
content: ciFeatureContent,
|
content: ciFeatureContent,
|
||||||
quotedItem: nil,
|
quotedItem: nil,
|
||||||
file: nil
|
file: nil
|
||||||
),
|
)
|
||||||
revealed: Binding.constant(true)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
.environment(\.revealed, true)
|
||||||
.previewLayout(.fixed(width: 360, height: 70))
|
.previewLayout(.fixed(width: 360, height: 70))
|
||||||
.environmentObject(Chat.sampleData)
|
.environmentObject(Chat.sampleData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,6 +137,14 @@ struct ChatView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// it should be presented on top level in order to prevent a bug in SwiftUI on iOS 16 related to .focused() modifier in AddGroupMembersView's search field
|
||||||
|
.appSheet(isPresented: $showAddMembersSheet) {
|
||||||
|
Group {
|
||||||
|
if case let .group(groupInfo) = cInfo {
|
||||||
|
AddGroupMembersView(chat: chat, groupInfo: groupInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.sheet(isPresented: Binding(
|
.sheet(isPresented: Binding(
|
||||||
get: { !forwardedChatItems.isEmpty },
|
get: { !forwardedChatItems.isEmpty },
|
||||||
set: { isPresented in
|
set: { isPresented in
|
||||||
@@ -304,9 +312,6 @@ struct ChatView: View {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
addMembersButton()
|
addMembersButton()
|
||||||
.appSheet(isPresented: $showAddMembersSheet) {
|
|
||||||
AddGroupMembersView(chat: chat, groupInfo: groupInfo)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Menu {
|
Menu {
|
||||||
@@ -1178,11 +1183,11 @@ struct ChatView: View {
|
|||||||
chat: chat,
|
chat: chat,
|
||||||
chatItem: ci,
|
chatItem: ci,
|
||||||
maxWidth: maxWidth,
|
maxWidth: maxWidth,
|
||||||
revealed: .constant(revealed),
|
|
||||||
allowMenu: $allowMenu
|
allowMenu: $allowMenu
|
||||||
)
|
)
|
||||||
|
.environment(\.revealed, revealed)
|
||||||
.environment(\.showTimestamp, itemSeparation.timestamp)
|
.environment(\.showTimestamp, itemSeparation.timestamp)
|
||||||
.modifier(ChatItemClipped(ci, tailVisible: itemSeparation.largeGap))
|
.modifier(ChatItemClipped(ci, tailVisible: itemSeparation.largeGap && (ci.meta.itemDeleted == nil || revealed)))
|
||||||
.contextMenu { menu(ci, range, live: composeState.liveMessage != nil) }
|
.contextMenu { menu(ci, range, live: composeState.liveMessage != nil) }
|
||||||
.accessibilityLabel("")
|
.accessibilityLabel("")
|
||||||
if ci.content.msgContent != nil && (ci.meta.itemDeleted == nil || revealed) && ci.reactions.count > 0 {
|
if ci.content.msgContent != nil && (ci.meta.itemDeleted == nil || revealed) && ci.reactions.count > 0 {
|
||||||
|
|||||||
@@ -287,8 +287,8 @@ struct ComposeView: View {
|
|||||||
// this is a workaround to fire an explicit event in certain cases
|
// this is a workaround to fire an explicit event in certain cases
|
||||||
@State private var stopPlayback: Bool = false
|
@State private var stopPlayback: Bool = false
|
||||||
|
|
||||||
@AppStorage(DEFAULT_PRIVACY_SAVE_LAST_DRAFT) private var saveLastDraft = true
|
@UserDefault(DEFAULT_PRIVACY_SAVE_LAST_DRAFT) private var saveLastDraft = true
|
||||||
@AppStorage(DEFAULT_TOOLBAR_MATERIAL) private var toolbarMaterial = ToolbarMaterial.defaultMaterial
|
@UserDefault(DEFAULT_TOOLBAR_MATERIAL) private var toolbarMaterial = ToolbarMaterial.defaultMaterial
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
@@ -459,7 +459,7 @@ struct ComposeView: View {
|
|||||||
Task {
|
Task {
|
||||||
var media: [(String, UploadContent)] = []
|
var media: [(String, UploadContent)] = []
|
||||||
for content in selected {
|
for content in selected {
|
||||||
if let img = resizeImageToStrSize(content.uiImage, maxDataSize: 14000) {
|
if let img = await resizeImageToStrSize(content.uiImage, maxDataSize: 14000) {
|
||||||
media.append((img, content))
|
media.append((img, content))
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
composeState = composeState.copy(preview: .mediaPreviews(mediaPreviews: media))
|
composeState = composeState.copy(preview: .mediaPreviews(mediaPreviews: media))
|
||||||
@@ -551,7 +551,7 @@ struct ComposeView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func addMediaContent(_ content: UploadContent) async {
|
private func addMediaContent(_ content: UploadContent) async {
|
||||||
if let img = resizeImageToStrSize(content.uiImage, maxDataSize: 14000) {
|
if let img = await resizeImageToStrSize(content.uiImage, maxDataSize: 14000) {
|
||||||
var newMedia: [(String, UploadContent?)] = []
|
var newMedia: [(String, UploadContent?)] = []
|
||||||
if case var .mediaPreviews(media) = composeState.preview {
|
if case var .mediaPreviews(media) = composeState.preview {
|
||||||
media.append((img, content))
|
media.append((img, content))
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ struct SendMessageView: View {
|
|||||||
@State private var showCustomTimePicker = false
|
@State private var showCustomTimePicker = false
|
||||||
@State private var selectedDisappearingMessageTime: Int? = customDisappearingMessageTimeDefault.get()
|
@State private var selectedDisappearingMessageTime: Int? = customDisappearingMessageTimeDefault.get()
|
||||||
@State private var progressByTimeout = false
|
@State private var progressByTimeout = false
|
||||||
@AppStorage(DEFAULT_LIVE_MESSAGE_ALERT_SHOWN) private var liveMessageAlertShown = false
|
@UserDefault(DEFAULT_LIVE_MESSAGE_ALERT_SHOWN) private var liveMessageAlertShown = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ struct GroupMemberInfoView: View {
|
|||||||
var navigation: Bool = false
|
var navigation: Bool = false
|
||||||
@State private var connectionStats: ConnectionStats? = nil
|
@State private var connectionStats: ConnectionStats? = nil
|
||||||
@State private var connectionCode: String? = nil
|
@State private var connectionCode: String? = nil
|
||||||
|
@State private var connectionLoaded: Bool = false
|
||||||
@State private var newRole: GroupMemberRole = .member
|
@State private var newRole: GroupMemberRole = .member
|
||||||
@State private var alert: GroupMemberInfoViewAlert?
|
@State private var alert: GroupMemberInfoViewAlert?
|
||||||
@State private var sheet: PlanAndConnectActionSheet?
|
@State private var sheet: PlanAndConnectActionSheet?
|
||||||
@@ -94,129 +95,137 @@ struct GroupMemberInfoView: View {
|
|||||||
.listRowSeparator(.hidden)
|
.listRowSeparator(.hidden)
|
||||||
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
|
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
|
||||||
|
|
||||||
if member.memberActive {
|
if connectionLoaded {
|
||||||
Section {
|
|
||||||
if let code = connectionCode { verifyCodeButton(code) }
|
|
||||||
if let connStats = connectionStats,
|
|
||||||
connStats.ratchetSyncAllowed {
|
|
||||||
synchronizeConnectionButton()
|
|
||||||
}
|
|
||||||
// } else if developerTools {
|
|
||||||
// synchronizeConnectionButtonForce()
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let contactLink = member.contactLink {
|
if member.memberActive {
|
||||||
Section {
|
Section {
|
||||||
SimpleXLinkQRCode(uri: contactLink)
|
if let code = connectionCode { verifyCodeButton(code) }
|
||||||
Button {
|
if let connStats = connectionStats,
|
||||||
showShareSheet(items: [simplexChatLink(contactLink)])
|
connStats.ratchetSyncAllowed {
|
||||||
} label: {
|
synchronizeConnectionButton()
|
||||||
Label("Share address", systemImage: "square.and.arrow.up")
|
}
|
||||||
|
// } else if developerTools {
|
||||||
|
// synchronizeConnectionButtonForce()
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
if let contactId = member.memberContactId {
|
}
|
||||||
if knownDirectChat(contactId) == nil && !groupInfo.fullGroupPreferences.directMessages.on(for: groupInfo.membership) {
|
|
||||||
|
if let contactLink = member.contactLink {
|
||||||
|
Section {
|
||||||
|
SimpleXLinkQRCode(uri: contactLink)
|
||||||
|
Button {
|
||||||
|
showShareSheet(items: [simplexChatLink(contactLink)])
|
||||||
|
} label: {
|
||||||
|
Label("Share address", systemImage: "square.and.arrow.up")
|
||||||
|
}
|
||||||
|
if let contactId = member.memberContactId {
|
||||||
|
if knownDirectChat(contactId) == nil && !groupInfo.fullGroupPreferences.directMessages.on(for: groupInfo.membership) {
|
||||||
|
connectViaAddressButton(contactLink)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
connectViaAddressButton(contactLink)
|
connectViaAddressButton(contactLink)
|
||||||
}
|
}
|
||||||
} else {
|
} header: {
|
||||||
connectViaAddressButton(contactLink)
|
Text("Address")
|
||||||
|
.foregroundColor(theme.colors.secondary)
|
||||||
|
} footer: {
|
||||||
|
Text("You can share this address with your contacts to let them connect with **\(member.displayName)**.")
|
||||||
|
.foregroundColor(theme.colors.secondary)
|
||||||
}
|
}
|
||||||
} header: {
|
|
||||||
Text("Address")
|
|
||||||
.foregroundColor(theme.colors.secondary)
|
|
||||||
} footer: {
|
|
||||||
Text("You can share this address with your contacts to let them connect with **\(member.displayName)**.")
|
|
||||||
.foregroundColor(theme.colors.secondary)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Section(header: Text("Member").foregroundColor(theme.colors.secondary)) {
|
Section(header: Text("Member").foregroundColor(theme.colors.secondary)) {
|
||||||
infoRow("Group", groupInfo.displayName)
|
infoRow("Group", groupInfo.displayName)
|
||||||
|
|
||||||
if let roles = member.canChangeRoleTo(groupInfo: groupInfo) {
|
if let roles = member.canChangeRoleTo(groupInfo: groupInfo) {
|
||||||
Picker("Change role", selection: $newRole) {
|
Picker("Change role", selection: $newRole) {
|
||||||
ForEach(roles) { role in
|
ForEach(roles) { role in
|
||||||
Text(role.text)
|
Text(role.text)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
.frame(height: 36)
|
||||||
|
} else {
|
||||||
|
infoRow("Role", member.memberRole.text)
|
||||||
}
|
}
|
||||||
.frame(height: 36)
|
|
||||||
} else {
|
|
||||||
infoRow("Role", member.memberRole.text)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let connStats = connectionStats {
|
if let connStats = connectionStats {
|
||||||
Section(header: Text("Servers").foregroundColor(theme.colors.secondary)) {
|
Section(header: Text("Servers").foregroundColor(theme.colors.secondary)) {
|
||||||
// TODO network connection status
|
// TODO network connection status
|
||||||
Button("Change receiving address") {
|
Button("Change receiving address") {
|
||||||
alert = .switchAddressAlert
|
alert = .switchAddressAlert
|
||||||
}
|
|
||||||
.disabled(
|
|
||||||
connStats.rcvQueuesInfo.contains { $0.rcvSwitchStatus != nil }
|
|
||||||
|| connStats.ratchetSyncSendProhibited
|
|
||||||
)
|
|
||||||
if connStats.rcvQueuesInfo.contains(where: { $0.rcvSwitchStatus != nil }) {
|
|
||||||
Button("Abort changing address") {
|
|
||||||
alert = .abortSwitchAddressAlert
|
|
||||||
}
|
}
|
||||||
.disabled(
|
.disabled(
|
||||||
connStats.rcvQueuesInfo.contains { $0.rcvSwitchStatus != nil && !$0.canAbortSwitch }
|
connStats.rcvQueuesInfo.contains { $0.rcvSwitchStatus != nil }
|
||||||
|| connStats.ratchetSyncSendProhibited
|
|| connStats.ratchetSyncSendProhibited
|
||||||
)
|
)
|
||||||
|
if connStats.rcvQueuesInfo.contains(where: { $0.rcvSwitchStatus != nil }) {
|
||||||
|
Button("Abort changing address") {
|
||||||
|
alert = .abortSwitchAddressAlert
|
||||||
|
}
|
||||||
|
.disabled(
|
||||||
|
connStats.rcvQueuesInfo.contains { $0.rcvSwitchStatus != nil && !$0.canAbortSwitch }
|
||||||
|
|| connStats.ratchetSyncSendProhibited
|
||||||
|
)
|
||||||
|
}
|
||||||
|
smpServers("Receiving via", connStats.rcvQueuesInfo.map { $0.rcvServer }, theme.colors.secondary)
|
||||||
|
smpServers("Sending via", connStats.sndQueuesInfo.map { $0.sndServer }, theme.colors.secondary)
|
||||||
}
|
}
|
||||||
smpServers("Receiving via", connStats.rcvQueuesInfo.map { $0.rcvServer }, theme.colors.secondary)
|
|
||||||
smpServers("Sending via", connStats.sndQueuesInfo.map { $0.sndServer }, theme.colors.secondary)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if groupInfo.membership.memberRole >= .admin {
|
if groupInfo.membership.memberRole >= .admin {
|
||||||
adminDestructiveSection(member)
|
adminDestructiveSection(member)
|
||||||
} else {
|
} else {
|
||||||
nonAdminBlockSection(member)
|
nonAdminBlockSection(member)
|
||||||
}
|
}
|
||||||
|
|
||||||
if developerTools {
|
if developerTools {
|
||||||
Section(header: Text("For console").foregroundColor(theme.colors.secondary)) {
|
Section(header: Text("For console").foregroundColor(theme.colors.secondary)) {
|
||||||
infoRow("Local name", member.localDisplayName)
|
infoRow("Local name", member.localDisplayName)
|
||||||
infoRow("Database ID", "\(member.groupMemberId)")
|
infoRow("Database ID", "\(member.groupMemberId)")
|
||||||
if let conn = member.activeConn {
|
if let conn = member.activeConn {
|
||||||
let connLevelDesc = conn.connLevel == 0 ? NSLocalizedString("direct", comment: "connection level description") : String.localizedStringWithFormat(NSLocalizedString("indirect (%d)", comment: "connection level description"), conn.connLevel)
|
let connLevelDesc = conn.connLevel == 0 ? NSLocalizedString("direct", comment: "connection level description") : String.localizedStringWithFormat(NSLocalizedString("indirect (%d)", comment: "connection level description"), conn.connLevel)
|
||||||
infoRow("Connection", connLevelDesc)
|
infoRow("Connection", connLevelDesc)
|
||||||
}
|
}
|
||||||
Button ("Debug delivery") {
|
Button ("Debug delivery") {
|
||||||
Task {
|
Task {
|
||||||
do {
|
do {
|
||||||
let info = queueInfoText(try await apiGroupMemberQueueInfo(groupInfo.apiId, member.groupMemberId))
|
let info = queueInfoText(try await apiGroupMemberQueueInfo(groupInfo.apiId, member.groupMemberId))
|
||||||
await MainActor.run { alert = .queueInfo(info: info) }
|
await MainActor.run { alert = .queueInfo(info: info) }
|
||||||
} catch let e {
|
} catch let e {
|
||||||
logger.error("apiContactQueueInfo error: \(responseError(e))")
|
logger.error("apiContactQueueInfo error: \(responseError(e))")
|
||||||
let a = getErrorAlert(e, "Error")
|
let a = getErrorAlert(e, "Error")
|
||||||
await MainActor.run { alert = .error(title: a.title, error: a.message) }
|
await MainActor.run { alert = .error(title: a.title, error: a.message) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationBarHidden(true)
|
.navigationBarHidden(true)
|
||||||
.onAppear {
|
.task {
|
||||||
if #unavailable(iOS 16) {
|
if #unavailable(iOS 16) {
|
||||||
// this condition prevents re-setting picker
|
// this condition prevents re-setting picker
|
||||||
if !justOpened { return }
|
if !justOpened { return }
|
||||||
}
|
}
|
||||||
justOpened = false
|
justOpened = false
|
||||||
DispatchQueue.main.async {
|
newRole = member.memberRole
|
||||||
newRole = member.memberRole
|
do {
|
||||||
do {
|
let (_, stats) = try await apiGroupMemberInfo(groupInfo.apiId, member.groupMemberId)
|
||||||
let (_, stats) = try apiGroupMemberInfo(groupInfo.apiId, member.groupMemberId)
|
let (mem, code) = member.memberActive ? try await apiGetGroupMemberCode(groupInfo.apiId, member.groupMemberId) : (member, nil)
|
||||||
let (mem, code) = member.memberActive ? try apiGetGroupMemberCode(groupInfo.apiId, member.groupMemberId) : (member, nil)
|
await MainActor.run {
|
||||||
_ = chatModel.upsertGroupMember(groupInfo, mem)
|
_ = chatModel.upsertGroupMember(groupInfo, mem)
|
||||||
connectionStats = stats
|
connectionStats = stats
|
||||||
connectionCode = code
|
connectionCode = code
|
||||||
} catch let error {
|
connectionLoaded = true
|
||||||
logger.error("apiGroupMemberInfo or apiGetGroupMemberCode error: \(responseError(error))")
|
|
||||||
}
|
}
|
||||||
|
} catch let error {
|
||||||
|
await MainActor.run {
|
||||||
|
connectionLoaded = true
|
||||||
|
}
|
||||||
|
logger.error("apiGroupMemberInfo or apiGetGroupMemberCode error: \(responseError(error))")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onChange(of: newRole) { newRole in
|
.onChange(of: newRole) { newRole in
|
||||||
|
|||||||
@@ -110,10 +110,13 @@ struct GroupProfileView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onChange(of: chosenImage) { image in
|
.onChange(of: chosenImage) { image in
|
||||||
if let image = image {
|
Task {
|
||||||
groupProfile.image = resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500)
|
let resized: String? = if let image {
|
||||||
} else {
|
await resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500)
|
||||||
groupProfile.image = nil
|
} else {
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
await MainActor.run { groupProfile.image = resized }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
|
|||||||
self.dataSource = UITableViewDiffableDataSource<Section, ChatItem>(
|
self.dataSource = UITableViewDiffableDataSource<Section, ChatItem>(
|
||||||
tableView: tableView
|
tableView: tableView
|
||||||
) { (tableView, indexPath, item) -> UITableViewCell? in
|
) { (tableView, indexPath, item) -> UITableViewCell? in
|
||||||
if indexPath.item > self.itemCount - 8, self.itemCount > 8 {
|
if indexPath.item > self.itemCount - 8 {
|
||||||
self.representer.loadPage()
|
self.representer.loadPage()
|
||||||
}
|
}
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseId, for: indexPath)
|
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseId, for: indexPath)
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ struct SelectedItemsBottomToolbar: View {
|
|||||||
|
|
||||||
@State var forwardEnabled: Bool = false
|
@State var forwardEnabled: Bool = false
|
||||||
|
|
||||||
@State var allButtonsDisabled = false
|
@State var deleteCountProhibited = false
|
||||||
|
@State var forwardCountProhibited = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
@@ -55,9 +56,9 @@ struct SelectedItemsBottomToolbar: View {
|
|||||||
.resizable()
|
.resizable()
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.frame(width: 20, height: 20, alignment: .center)
|
.frame(width: 20, height: 20, alignment: .center)
|
||||||
.foregroundColor(!deleteEnabled || allButtonsDisabled ? theme.colors.secondary: .red)
|
.foregroundColor(!deleteEnabled || deleteCountProhibited ? theme.colors.secondary: .red)
|
||||||
}
|
}
|
||||||
.disabled(!deleteEnabled || allButtonsDisabled)
|
.disabled(!deleteEnabled || deleteCountProhibited)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
Button {
|
Button {
|
||||||
@@ -67,9 +68,9 @@ struct SelectedItemsBottomToolbar: View {
|
|||||||
.resizable()
|
.resizable()
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.frame(width: 20, height: 20, alignment: .center)
|
.frame(width: 20, height: 20, alignment: .center)
|
||||||
.foregroundColor(!moderateEnabled || allButtonsDisabled ? theme.colors.secondary : .red)
|
.foregroundColor(!moderateEnabled || deleteCountProhibited ? theme.colors.secondary : .red)
|
||||||
}
|
}
|
||||||
.disabled(!moderateEnabled || allButtonsDisabled)
|
.disabled(!moderateEnabled || deleteCountProhibited)
|
||||||
.opacity(canModerate ? 1 : 0)
|
.opacity(canModerate ? 1 : 0)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
@@ -80,9 +81,9 @@ struct SelectedItemsBottomToolbar: View {
|
|||||||
.resizable()
|
.resizable()
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.frame(width: 20, height: 20, alignment: .center)
|
.frame(width: 20, height: 20, alignment: .center)
|
||||||
.foregroundColor(!forwardEnabled || allButtonsDisabled ? theme.colors.secondary : theme.colors.primary)
|
.foregroundColor(!forwardEnabled || forwardCountProhibited ? theme.colors.secondary : theme.colors.primary)
|
||||||
}
|
}
|
||||||
.disabled(!forwardEnabled || allButtonsDisabled)
|
.disabled(!forwardEnabled || forwardCountProhibited)
|
||||||
}
|
}
|
||||||
.frame(maxHeight: .infinity)
|
.frame(maxHeight: .infinity)
|
||||||
.padding([.leading, .trailing], 12)
|
.padding([.leading, .trailing], 12)
|
||||||
@@ -105,7 +106,8 @@ struct SelectedItemsBottomToolbar: View {
|
|||||||
|
|
||||||
private func recheckItems(_ chatInfo: ChatInfo, _ chatItems: [ChatItem], _ selectedItems: Set<Int64>?) {
|
private func recheckItems(_ chatInfo: ChatInfo, _ chatItems: [ChatItem], _ selectedItems: Set<Int64>?) {
|
||||||
let count = selectedItems?.count ?? 0
|
let count = selectedItems?.count ?? 0
|
||||||
allButtonsDisabled = count == 0 || count > 20
|
deleteCountProhibited = count == 0 || count > 200
|
||||||
|
forwardCountProhibited = count == 0 || count > 20
|
||||||
canModerate = possibleToModerate(chatInfo)
|
canModerate = possibleToModerate(chatInfo)
|
||||||
if let selected = selectedItems {
|
if let selected = selectedItems {
|
||||||
let me: Bool
|
let me: Bool
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import SwiftUI
|
|||||||
|
|
||||||
struct ChatHelp: View {
|
struct ChatHelp: View {
|
||||||
@EnvironmentObject var chatModel: ChatModel
|
@EnvironmentObject var chatModel: ChatModel
|
||||||
@Binding var showSettings: Bool
|
let dismissSettingsSheet: DismissAction
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView { chatHelp() }
|
ScrollView { chatHelp() }
|
||||||
@@ -23,7 +23,7 @@ struct ChatHelp: View {
|
|||||||
VStack(alignment: .leading, spacing: 0) {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
Text("To ask any questions and to receive updates:")
|
Text("To ask any questions and to receive updates:")
|
||||||
Button("connect to SimpleX Chat developers.") {
|
Button("connect to SimpleX Chat developers.") {
|
||||||
showSettings = false
|
dismissSettingsSheet()
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
UIApplication.shared.open(simplexTeamURL)
|
UIApplication.shared.open(simplexTeamURL)
|
||||||
}
|
}
|
||||||
@@ -61,8 +61,9 @@ struct ChatHelp: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ChatHelp_Previews: PreviewProvider {
|
struct ChatHelp_Previews: PreviewProvider {
|
||||||
|
@Environment(\.dismiss) static var mockDismiss
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
@State var showSettings = false
|
ChatHelp(dismissSettingsSheet: mockDismiss)
|
||||||
return ChatHelp(showSettings: $showSettings)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,19 +18,77 @@ enum UserPickerSheet: Identifiable {
|
|||||||
case settings
|
case settings
|
||||||
|
|
||||||
var id: Self { self }
|
var id: Self { self }
|
||||||
|
|
||||||
|
var navigationTitle: LocalizedStringKey {
|
||||||
|
switch self {
|
||||||
|
case .address: "SimpleX address"
|
||||||
|
case .chatPreferences: "Your preferences"
|
||||||
|
case .chatProfiles: "Your chat profiles"
|
||||||
|
case .currentProfile: "Your current profile"
|
||||||
|
case .useFromDesktop: "Connect to desktop"
|
||||||
|
case .settings: "Your settings"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct UserPickerSheetView: View {
|
||||||
|
let sheet: UserPickerSheet
|
||||||
|
@EnvironmentObject var chatModel: ChatModel
|
||||||
|
@State private var loaded = false
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationView {
|
||||||
|
ZStack {
|
||||||
|
if loaded, let currentUser = chatModel.currentUser {
|
||||||
|
switch sheet {
|
||||||
|
case .address:
|
||||||
|
UserAddressView(shareViaProfile: currentUser.addressShared)
|
||||||
|
case .chatPreferences:
|
||||||
|
PreferencesView(
|
||||||
|
profile: currentUser.profile,
|
||||||
|
preferences: currentUser.fullPreferences,
|
||||||
|
currentPreferences: currentUser.fullPreferences
|
||||||
|
)
|
||||||
|
case .chatProfiles:
|
||||||
|
UserProfilesView()
|
||||||
|
case .currentProfile:
|
||||||
|
UserProfile()
|
||||||
|
case .useFromDesktop:
|
||||||
|
ConnectDesktopView()
|
||||||
|
case .settings:
|
||||||
|
SettingsView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Color.clear // Required for list background to be rendered during loading
|
||||||
|
}
|
||||||
|
.navigationTitle(sheet.navigationTitle)
|
||||||
|
.navigationBarTitleDisplayMode(.large)
|
||||||
|
.modifier(ThemedBackground(grouped: true))
|
||||||
|
}
|
||||||
|
.overlay {
|
||||||
|
if let la = chatModel.laRequest {
|
||||||
|
LocalAuthView(authRequest: la)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.task {
|
||||||
|
withAnimation(
|
||||||
|
.easeOut(duration: 0.1),
|
||||||
|
{ loaded = true }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ChatListView: View {
|
struct ChatListView: View {
|
||||||
@EnvironmentObject var chatModel: ChatModel
|
@EnvironmentObject var chatModel: ChatModel
|
||||||
@EnvironmentObject var theme: AppTheme
|
@EnvironmentObject var theme: AppTheme
|
||||||
@Binding var showSettings: Bool
|
@Binding var activeUserPickerSheet: UserPickerSheet?
|
||||||
@State private var searchMode = false
|
@State private var searchMode = false
|
||||||
@FocusState private var searchFocussed
|
@FocusState private var searchFocussed
|
||||||
@State private var searchText = ""
|
@State private var searchText = ""
|
||||||
@State private var searchShowingSimplexLink = false
|
@State private var searchShowingSimplexLink = false
|
||||||
@State private var searchChatFilteredBySimplexLink: String? = nil
|
@State private var searchChatFilteredBySimplexLink: String? = nil
|
||||||
@State private var scrollToSearchBar = false
|
@State private var scrollToSearchBar = false
|
||||||
@State private var activeUserPickerSheet: UserPickerSheet? = nil
|
|
||||||
@State private var userPickerShown: Bool = false
|
@State private var userPickerShown: Bool = false
|
||||||
|
|
||||||
@AppStorage(DEFAULT_SHOW_UNREAD_AND_FAVORITES) private var showUnreadAndFavorites = false
|
@AppStorage(DEFAULT_SHOW_UNREAD_AND_FAVORITES) private var showUnreadAndFavorites = false
|
||||||
@@ -58,43 +116,22 @@ struct ChatListView: View {
|
|||||||
destination: chatView
|
destination: chatView
|
||||||
) { chatListView }
|
) { chatListView }
|
||||||
}
|
}
|
||||||
.sheet(isPresented: $userPickerShown) {
|
.modifier(
|
||||||
UserPicker(activeSheet: $activeUserPickerSheet)
|
Sheet(isPresented: $userPickerShown) {
|
||||||
.sheet(item: $activeUserPickerSheet) { sheet in
|
UserPicker(userPickerShown: $userPickerShown, activeSheet: $activeUserPickerSheet)
|
||||||
if let currentUser = chatModel.currentUser {
|
}
|
||||||
switch sheet {
|
)
|
||||||
case .address:
|
.appSheet(
|
||||||
NavigationView {
|
item: $activeUserPickerSheet,
|
||||||
UserAddressView(shareViaProfile: currentUser.addressShared)
|
onDismiss: { chatModel.laRequest = nil },
|
||||||
.navigationTitle("SimpleX address")
|
content: { UserPickerSheetView(sheet: $0) }
|
||||||
.navigationBarTitleDisplayMode(.large)
|
)
|
||||||
.modifier(ThemedBackground(grouped: true))
|
.onChange(of: activeUserPickerSheet) {
|
||||||
}
|
if $0 != nil {
|
||||||
case .chatProfiles:
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
|
||||||
NavigationView {
|
userPickerShown = false
|
||||||
UserProfilesView()
|
|
||||||
}
|
|
||||||
case .currentProfile:
|
|
||||||
NavigationView {
|
|
||||||
UserProfile()
|
|
||||||
.navigationTitle("Your current profile")
|
|
||||||
.modifier(ThemedBackground(grouped: true))
|
|
||||||
}
|
|
||||||
case .chatPreferences:
|
|
||||||
NavigationView {
|
|
||||||
PreferencesView(profile: currentUser.profile, preferences: currentUser.fullPreferences, currentPreferences: currentUser.fullPreferences)
|
|
||||||
.navigationTitle("Your preferences")
|
|
||||||
.navigationBarTitleDisplayMode(.large)
|
|
||||||
.modifier(ThemedBackground(grouped: true))
|
|
||||||
}
|
|
||||||
case .useFromDesktop:
|
|
||||||
ConnectDesktopView(viaSettings: false)
|
|
||||||
case .settings:
|
|
||||||
SettingsView(showSettings: $showSettings)
|
|
||||||
.navigationBarTitleDisplayMode(.large)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,7 +439,7 @@ struct SubsStatusIndicator: View {
|
|||||||
private func startTask() {
|
private func startTask() {
|
||||||
task = Task {
|
task = Task {
|
||||||
while !Task.isCancelled {
|
while !Task.isCancelled {
|
||||||
if AppChatState.shared.value == .active {
|
if AppChatState.shared.value == .active, ChatModel.shared.chatRunning == true {
|
||||||
do {
|
do {
|
||||||
let (subs, hasSess) = try await getAgentSubsTotal()
|
let (subs, hasSess) = try await getAgentSubsTotal()
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
@@ -544,6 +581,8 @@ func chatStoppedIcon() -> some View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ChatListView_Previews: PreviewProvider {
|
struct ChatListView_Previews: PreviewProvider {
|
||||||
|
@State static var userPickerSheet: UserPickerSheet? = .none
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let chatModel = ChatModel()
|
let chatModel = ChatModel()
|
||||||
chatModel.updateChats([
|
chatModel.updateChats([
|
||||||
@@ -562,9 +601,9 @@ struct ChatListView_Previews: PreviewProvider {
|
|||||||
|
|
||||||
])
|
])
|
||||||
return Group {
|
return Group {
|
||||||
ChatListView(showSettings: Binding.constant(false))
|
ChatListView(activeUserPickerSheet: $userPickerSheet)
|
||||||
.environmentObject(chatModel)
|
.environmentObject(chatModel)
|
||||||
ChatListView(showSettings: Binding.constant(false))
|
ChatListView(activeUserPickerSheet: $userPickerSheet)
|
||||||
.environmentObject(ChatModel())
|
.environmentObject(ChatModel())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,42 +12,31 @@ struct UserPicker: View {
|
|||||||
@Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize
|
@Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize
|
||||||
@Environment(\.scenePhase) private var scenePhase: ScenePhase
|
@Environment(\.scenePhase) private var scenePhase: ScenePhase
|
||||||
@Environment(\.colorScheme) private var colorScheme: ColorScheme
|
@Environment(\.colorScheme) private var colorScheme: ColorScheme
|
||||||
@Environment(\.dismiss) private var dismiss: DismissAction
|
@Binding var userPickerShown: Bool
|
||||||
@Binding var activeSheet: UserPickerSheet?
|
@Binding var activeSheet: UserPickerSheet?
|
||||||
@State private var currentUser: Int64?
|
@State private var currentUser: Int64?
|
||||||
@State private var switchingProfile = false
|
@State private var switchingProfile = false
|
||||||
@State private var frameWidth: CGFloat = 0
|
@State private var frameWidth: CGFloat = 0
|
||||||
|
@State private var resetScroll = ResetScrollAction()
|
||||||
|
|
||||||
// Inset grouped list dimensions
|
// Inset grouped list dimensions
|
||||||
private let imageSize: CGFloat = 44
|
private let imageSize: CGFloat = 44
|
||||||
private let rowPadding: CGFloat = 16
|
private let rowPadding: CGFloat = 16
|
||||||
|
private let rowVerticalPadding: CGFloat = 11
|
||||||
private let sectionSpacing: CGFloat = 35
|
private let sectionSpacing: CGFloat = 35
|
||||||
private var sectionHorizontalPadding: CGFloat { frameWidth > 375 ? 20 : 16 }
|
private var sectionHorizontalPadding: CGFloat { frameWidth > 375 ? 20 : 16 }
|
||||||
private let sectionShape = RoundedRectangle(cornerRadius: 10, style: .continuous)
|
private let sectionShape = RoundedRectangle(cornerRadius: 10, style: .continuous)
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if #available(iOS 16.0, *) {
|
|
||||||
let v = viewBody.presentationDetents([.height(400)])
|
|
||||||
if #available(iOS 16.4, *) {
|
|
||||||
v.scrollBounceBehavior(.basedOnSize)
|
|
||||||
} else {
|
|
||||||
v
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
viewBody
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ViewBuilder
|
|
||||||
private var viewBody: some View {
|
|
||||||
let otherUsers: [UserInfo] = m.users
|
let otherUsers: [UserInfo] = m.users
|
||||||
.filter { u in !u.user.hidden && u.user.userId != m.currentUser?.userId }
|
.filter { u in !u.user.hidden && u.user.userId != m.currentUser?.userId }
|
||||||
.sorted(using: KeyPathComparator<UserInfo>(\.user.activeOrder, order: .reverse))
|
.sorted(using: KeyPathComparator<UserInfo>(\.user.activeOrder, order: .reverse))
|
||||||
let sectionWidth = max(frameWidth - sectionHorizontalPadding * 2, 0)
|
let sectionWidth = max(frameWidth - sectionHorizontalPadding * 2, 0)
|
||||||
let currentUserWidth = max(frameWidth - sectionHorizontalPadding - rowPadding * 2 - 14 - imageSize, 0)
|
let currentUserWidth = max(frameWidth - sectionHorizontalPadding - rowPadding * 2 - 14 - imageSize, 0)
|
||||||
VStack(spacing: 0) {
|
let stopped = m.chatRunning != true
|
||||||
|
VStack(spacing: sectionSpacing) {
|
||||||
if let user = m.currentUser {
|
if let user = m.currentUser {
|
||||||
StickyScrollView {
|
StickyScrollView(resetScroll: $resetScroll) {
|
||||||
HStack(spacing: rowPadding) {
|
HStack(spacing: rowPadding) {
|
||||||
HStack {
|
HStack {
|
||||||
ProfileImage(imageStr: user.image, size: imageSize, color: Color(uiColor: .tertiarySystemGroupedBackground))
|
ProfileImage(imageStr: user.image, size: imageSize, color: Color(uiColor: .tertiarySystemGroupedBackground))
|
||||||
@@ -56,13 +45,16 @@ struct UserPicker: View {
|
|||||||
}
|
}
|
||||||
.padding(rowPadding)
|
.padding(rowPadding)
|
||||||
.frame(width: otherUsers.isEmpty ? sectionWidth : currentUserWidth, alignment: .leading)
|
.frame(width: otherUsers.isEmpty ? sectionWidth : currentUserWidth, alignment: .leading)
|
||||||
.background(Color(.secondarySystemGroupedBackground))
|
.modifier(ListRow { activeSheet = .currentProfile })
|
||||||
.clipShape(sectionShape)
|
.clipShape(sectionShape)
|
||||||
.onTapGesture { activeSheet = .currentProfile }
|
.disabled(stopped)
|
||||||
|
.opacity(stopped ? 0.4 : 1)
|
||||||
ForEach(otherUsers) { u in
|
ForEach(otherUsers) { u in
|
||||||
userView(u, size: imageSize)
|
userView(u, size: imageSize)
|
||||||
.frame(maxWidth: sectionWidth * 0.618)
|
.frame(maxWidth: sectionWidth * 0.618)
|
||||||
.fixedSize()
|
.fixedSize()
|
||||||
|
.disabled(stopped)
|
||||||
|
.opacity(stopped ? 0.4 : 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.horizontal, sectionHorizontalPadding)
|
.padding(.horizontal, sectionHorizontalPadding)
|
||||||
@@ -72,20 +64,21 @@ struct UserPicker: View {
|
|||||||
.overlay(DetermineWidth())
|
.overlay(DetermineWidth())
|
||||||
.onPreferenceChange(DetermineWidth.Key.self) { frameWidth = $0 }
|
.onPreferenceChange(DetermineWidth.Key.self) { frameWidth = $0 }
|
||||||
}
|
}
|
||||||
List {
|
VStack(spacing: 0) {
|
||||||
Section {
|
openSheetOnTap("qrcode", title: m.userAddress == nil ? "Create SimpleX address" : "Your SimpleX address", sheet: .address, disabled: stopped)
|
||||||
openSheetOnTap("qrcode", title: m.userAddress == nil ? "Create SimpleX address" : "Your SimpleX address", sheet: .address)
|
openSheetOnTap("switch.2", title: "Chat preferences", sheet: .chatPreferences, disabled: stopped)
|
||||||
openSheetOnTap("switch.2", title: "Chat preferences", sheet: .chatPreferences)
|
openSheetOnTap("person.crop.rectangle.stack", title: "Your chat profiles", sheet: .chatProfiles, disabled: stopped)
|
||||||
openSheetOnTap("person.crop.rectangle.stack", title: "Your chat profiles", sheet: .chatProfiles)
|
openSheetOnTap("desktopcomputer", title: "Use from desktop", sheet: .useFromDesktop, disabled: stopped)
|
||||||
openSheetOnTap("desktopcomputer", title: "Use from desktop", sheet: .useFromDesktop)
|
ZStack(alignment: .trailing) {
|
||||||
|
openSheetOnTap("gearshape", title: "Settings", sheet: .settings, showDivider: false)
|
||||||
ZStack(alignment: .trailing) {
|
Image(systemName: colorScheme == .light ? "sun.max" : "moon.fill")
|
||||||
openSheetOnTap("gearshape", title: "Settings", sheet: .settings)
|
|
||||||
Image(systemName: colorScheme == .light ? "sun.max" : "moon.fill")
|
|
||||||
.resizable()
|
.resizable()
|
||||||
|
.scaledToFit()
|
||||||
.symbolRenderingMode(.monochrome)
|
.symbolRenderingMode(.monochrome)
|
||||||
.foregroundColor(theme.colors.secondary)
|
.foregroundColor(theme.colors.secondary)
|
||||||
.frame(maxWidth: 20, maxHeight: 20)
|
.frame(maxWidth: 20, maxHeight: .infinity)
|
||||||
|
.padding(.horizontal, rowPadding)
|
||||||
|
.background(Color(.systemBackground).opacity(0.01))
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
if (colorScheme == .light) {
|
if (colorScheme == .light) {
|
||||||
ThemeManager.applyTheme(systemDarkThemeDefault.get())
|
ThemeManager.applyTheme(systemDarkThemeDefault.get())
|
||||||
@@ -96,9 +89,11 @@ struct UserPicker: View {
|
|||||||
.onLongPressGesture {
|
.onLongPressGesture {
|
||||||
ThemeManager.applyTheme(DefaultTheme.SYSTEM_THEME_NAME)
|
ThemeManager.applyTheme(DefaultTheme.SYSTEM_THEME_NAME)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.clipShape(sectionShape)
|
||||||
|
.padding(.horizontal, sectionHorizontalPadding)
|
||||||
|
.padding(.bottom, sectionSpacing)
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
// This check prevents the call of listUsers after the app is suspended, and the database is closed.
|
// This check prevents the call of listUsers after the app is suspended, and the database is closed.
|
||||||
@@ -117,6 +112,9 @@ struct UserPicker: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.onChange(of: userPickerShown) {
|
||||||
|
if !$0 { resetScroll() }
|
||||||
|
}
|
||||||
.modifier(ThemedBackground(grouped: true))
|
.modifier(ThemedBackground(grouped: true))
|
||||||
.disabled(switchingProfile)
|
.disabled(switchingProfile)
|
||||||
}
|
}
|
||||||
@@ -133,15 +131,15 @@ struct UserPicker: View {
|
|||||||
Text(u.user.displayName).font(.title2).lineLimit(1)
|
Text(u.user.displayName).font(.title2).lineLimit(1)
|
||||||
}
|
}
|
||||||
.padding(rowPadding)
|
.padding(rowPadding)
|
||||||
.background(Color(.secondarySystemGroupedBackground))
|
.modifier(ListRow {
|
||||||
.clipShape(sectionShape)
|
|
||||||
.onTapGesture {
|
|
||||||
switchingProfile = true
|
switchingProfile = true
|
||||||
dismiss()
|
|
||||||
Task {
|
Task {
|
||||||
do {
|
do {
|
||||||
try await changeActiveUserAsync_(u.user.userId, viewPwd: nil)
|
try await changeActiveUserAsync_(u.user.userId, viewPwd: nil)
|
||||||
await MainActor.run { switchingProfile = false }
|
await MainActor.run {
|
||||||
|
switchingProfile = false
|
||||||
|
userPickerShown = false
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
switchingProfile = false
|
switchingProfile = false
|
||||||
@@ -152,19 +150,24 @@ struct UserPicker: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
.clipShape(sectionShape)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func openSheetOnTap(_ icon: String, title: LocalizedStringKey, sheet: UserPickerSheet) -> some View {
|
private func openSheetOnTap(_ icon: String, title: LocalizedStringKey, sheet: UserPickerSheet, showDivider: Bool = true, disabled: Bool = false) -> some View {
|
||||||
Button {
|
ZStack(alignment: .bottom) {
|
||||||
activeSheet = sheet
|
|
||||||
} label: {
|
|
||||||
settingsRow(icon, color: theme.colors.secondary) {
|
settingsRow(icon, color: theme.colors.secondary) {
|
||||||
Text(title).foregroundColor(.primary)
|
Text(title).foregroundColor(.primary).opacity(disabled ? 0.4 : 1)
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.padding(.horizontal, rowPadding)
|
||||||
|
.padding(.vertical, rowVerticalPadding)
|
||||||
|
.modifier(ListRow { activeSheet = sheet })
|
||||||
|
.disabled(disabled)
|
||||||
|
if showDivider {
|
||||||
|
Divider().padding(.leading, 52)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
|
||||||
.contentShape(Rectangle())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func unreadBadge(_ u: UserInfo) -> some View {
|
private func unreadBadge(_ u: UserInfo) -> some View {
|
||||||
@@ -179,6 +182,92 @@ struct UserPicker: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ListRow: ViewModifier {
|
||||||
|
@Environment(\.colorScheme) private var colorScheme: ColorScheme
|
||||||
|
@State private var touchDown = false
|
||||||
|
let action: () -> Void
|
||||||
|
|
||||||
|
func body(content: Content) -> some View {
|
||||||
|
ZStack {
|
||||||
|
elevatedSecondarySystemGroupedBackground
|
||||||
|
Color(.systemGray4).opacity(touchDown ? 1 : 0)
|
||||||
|
content
|
||||||
|
TouchOverlay(touchDown: $touchDown, action: action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var elevatedSecondarySystemGroupedBackground: Color {
|
||||||
|
switch colorScheme {
|
||||||
|
case .dark: Color(0xFF2C2C2E)
|
||||||
|
default: Color(0xFFFFFFFF)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TouchOverlay: UIViewRepresentable {
|
||||||
|
@Binding var touchDown: Bool
|
||||||
|
let action: () -> Void
|
||||||
|
|
||||||
|
func makeUIView(context: Context) -> TouchView {
|
||||||
|
let touchView = TouchView()
|
||||||
|
let gesture = UILongPressGestureRecognizer(
|
||||||
|
target: touchView,
|
||||||
|
action: #selector(touchView.longPress(gesture:))
|
||||||
|
)
|
||||||
|
gesture.delegate = touchView
|
||||||
|
gesture.minimumPressDuration = 0
|
||||||
|
touchView.addGestureRecognizer(gesture)
|
||||||
|
return touchView
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUIView(_ touchView: TouchView, context: Context) {
|
||||||
|
touchView.representer = self
|
||||||
|
}
|
||||||
|
|
||||||
|
class TouchView: UIView, UIGestureRecognizerDelegate {
|
||||||
|
var representer: TouchOverlay?
|
||||||
|
private var startLocation: CGPoint?
|
||||||
|
private var task: Task<Void, Never>?
|
||||||
|
|
||||||
|
@objc
|
||||||
|
func longPress(gesture: UILongPressGestureRecognizer) {
|
||||||
|
switch gesture.state {
|
||||||
|
case .began:
|
||||||
|
startLocation = gesture.location(in: nil)
|
||||||
|
task = Task {
|
||||||
|
do {
|
||||||
|
try await Task.sleep(nanoseconds: 200_000000)
|
||||||
|
await MainActor.run { representer?.touchDown = true }
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
case .ended:
|
||||||
|
if hitTest(gesture.location(in: self), with: nil) == self {
|
||||||
|
representer?.action()
|
||||||
|
}
|
||||||
|
task?.cancel()
|
||||||
|
representer?.touchDown = false
|
||||||
|
case .changed:
|
||||||
|
if let startLocation {
|
||||||
|
let location = gesture.location(in: nil)
|
||||||
|
let dx = location.x - startLocation.x
|
||||||
|
let dy = location.y - startLocation.y
|
||||||
|
if sqrt(pow(dx, 2) + pow(dy, 2)) > 10 { gesture.state = .failed }
|
||||||
|
}
|
||||||
|
case .cancelled, .failed:
|
||||||
|
task?.cancel()
|
||||||
|
representer?.touchDown = false
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func gestureRecognizer(
|
||||||
|
_: UIGestureRecognizer,
|
||||||
|
shouldRecognizeSimultaneouslyWith: UIGestureRecognizer
|
||||||
|
) -> Bool { true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct UserPicker_Previews: PreviewProvider {
|
struct UserPicker_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
@State var activeSheet: UserPickerSheet?
|
@State var activeSheet: UserPickerSheet?
|
||||||
@@ -186,6 +275,7 @@ struct UserPicker_Previews: PreviewProvider {
|
|||||||
let m = ChatModel()
|
let m = ChatModel()
|
||||||
m.users = [UserInfo.sampleData, UserInfo.sampleData]
|
m.users = [UserInfo.sampleData, UserInfo.sampleData]
|
||||||
return UserPicker(
|
return UserPicker(
|
||||||
|
userPickerShown: .constant(true),
|
||||||
activeSheet: $activeSheet
|
activeSheet: $activeSheet
|
||||||
)
|
)
|
||||||
.environmentObject(m)
|
.environmentObject(m)
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ enum DatabaseAlert: Identifiable {
|
|||||||
struct DatabaseView: View {
|
struct DatabaseView: View {
|
||||||
@EnvironmentObject var m: ChatModel
|
@EnvironmentObject var m: ChatModel
|
||||||
@EnvironmentObject var theme: AppTheme
|
@EnvironmentObject var theme: AppTheme
|
||||||
@Binding var showSettings: Bool
|
let dismissSettingsSheet: DismissAction
|
||||||
@State private var runChat = false
|
@State private var runChat = false
|
||||||
@State private var alert: DatabaseAlert? = nil
|
@State private var alert: DatabaseAlert? = nil
|
||||||
@State private var showFileImporter = false
|
@State private var showFileImporter = false
|
||||||
@@ -439,7 +439,7 @@ struct DatabaseView: View {
|
|||||||
|
|
||||||
private func startChat() {
|
private func startChat() {
|
||||||
if m.chatDbChanged {
|
if m.chatDbChanged {
|
||||||
showSettings = false
|
dismissSettingsSheet()
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||||
resetChatCtrl()
|
resetChatCtrl()
|
||||||
do {
|
do {
|
||||||
@@ -533,7 +533,9 @@ func deleteChatAsync() async throws {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct DatabaseView_Previews: PreviewProvider {
|
struct DatabaseView_Previews: PreviewProvider {
|
||||||
|
@Environment(\.dismiss) static var mockDismiss
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
DatabaseView(showSettings: Binding.constant(false), chatItemTTL: .none)
|
DatabaseView(dismissSettingsSheet: mockDismiss, chatItemTTL: .none)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ import SwiftUI
|
|||||||
class AppSheetState: ObservableObject {
|
class AppSheetState: ObservableObject {
|
||||||
static let shared = AppSheetState()
|
static let shared = AppSheetState()
|
||||||
@Published var scenePhaseActive: Bool = false
|
@Published var scenePhaseActive: Bool = false
|
||||||
|
|
||||||
|
func redactionReasons(_ protectScreen: Bool) -> RedactionReasons {
|
||||||
|
!protectScreen || scenePhaseActive
|
||||||
|
? RedactionReasons()
|
||||||
|
: RedactionReasons.placeholder
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct PrivacySensitive: ViewModifier {
|
private struct PrivacySensitive: ViewModifier {
|
||||||
@@ -19,11 +25,7 @@ private struct PrivacySensitive: ViewModifier {
|
|||||||
@ObservedObject var appSheetState: AppSheetState = AppSheetState.shared
|
@ObservedObject var appSheetState: AppSheetState = AppSheetState.shared
|
||||||
|
|
||||||
func body(content: Content) -> some View {
|
func body(content: Content) -> some View {
|
||||||
if !protectScreen {
|
content.redacted(reason: appSheetState.redactionReasons(protectScreen))
|
||||||
content
|
|
||||||
} else {
|
|
||||||
content.privacySensitive(!appSheetState.scenePhaseActive).redacted(reason: .privacy)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,12 +36,7 @@ struct ChatItemClipped: ViewModifier {
|
|||||||
.sndMsgContent,
|
.sndMsgContent,
|
||||||
.rcvMsgContent,
|
.rcvMsgContent,
|
||||||
.rcvDecryptionError,
|
.rcvDecryptionError,
|
||||||
.sndDeleted,
|
|
||||||
.rcvDeleted,
|
|
||||||
.rcvIntegrityError,
|
.rcvIntegrityError,
|
||||||
.sndModerated,
|
|
||||||
.rcvModerated,
|
|
||||||
.rcvBlocked,
|
|
||||||
.invalidJSON:
|
.invalidJSON:
|
||||||
let tail = if let mc = ci.content.msgContent, mc.isImageOrVideo && mc.text.isEmpty {
|
let tail = if let mc = ci.content.msgContent, mc.isImageOrVideo && mc.text.isEmpty {
|
||||||
false
|
false
|
||||||
|
|||||||
@@ -0,0 +1,188 @@
|
|||||||
|
//
|
||||||
|
// SwiftUISheet.swift
|
||||||
|
// SimpleX (iOS)
|
||||||
|
//
|
||||||
|
// Created by user on 23/09/2024.
|
||||||
|
// Copyright © 2024 SimpleX Chat. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
private let sheetAnimationDuration: Double = 0.35
|
||||||
|
|
||||||
|
// Refrence: https://easings.net/
|
||||||
|
private let easeOutCubic = UICubicTimingParameters(
|
||||||
|
controlPoint1: CGPoint(x: 0.215, y: 0.61),
|
||||||
|
controlPoint2: CGPoint(x: 0.355, y: 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
struct Sheet<SheetContent: View>: ViewModifier {
|
||||||
|
@Binding var isPresented: Bool
|
||||||
|
@ViewBuilder let sheetContent: () -> SheetContent
|
||||||
|
|
||||||
|
func body(content: Content) -> some View {
|
||||||
|
ZStack {
|
||||||
|
content
|
||||||
|
SheetRepresentable(isPresented: $isPresented, content: sheetContent())
|
||||||
|
.allowsHitTesting(isPresented)
|
||||||
|
.ignoresSafeArea()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SheetRepresentable<Content: View>: UIViewControllerRepresentable {
|
||||||
|
@Binding var isPresented: Bool
|
||||||
|
let content: Content
|
||||||
|
|
||||||
|
func makeUIViewController(context: Context) -> Controller<Content> {
|
||||||
|
Controller(content: content, representer: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUIViewController(_ sheetController: Controller<Content>, context: Context) {
|
||||||
|
sheetController.animate(isPresented: isPresented)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Controller<C: View>: UIViewController {
|
||||||
|
let hostingController: UIHostingController<C>
|
||||||
|
private let animator = UIViewPropertyAnimator(
|
||||||
|
duration: sheetAnimationDuration,
|
||||||
|
timingParameters: easeOutCubic
|
||||||
|
)
|
||||||
|
private let representer: SheetRepresentable<C>
|
||||||
|
private var retainedFraction: CGFloat = 0
|
||||||
|
private var sheetHeight: Double { hostingController.view.frame.height }
|
||||||
|
private var task: Task<Void, Never>?
|
||||||
|
|
||||||
|
init(content: C, representer: SheetRepresentable<C>) {
|
||||||
|
self.representer = representer
|
||||||
|
self.hostingController = UIHostingController(rootView: content)
|
||||||
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, unavailable)
|
||||||
|
required init?(coder: NSCoder) { fatalError("init(coder:) missing") }
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
animator.stopAnimation(true)
|
||||||
|
animator.finishAnimation(at: .current)
|
||||||
|
}
|
||||||
|
|
||||||
|
func animate(isPresented: Bool) {
|
||||||
|
let alreadyAnimating = animator.isRunning && isPresented != animator.isReversed
|
||||||
|
let sheetFullyDismissed = animator.fractionComplete == (animator.isReversed ? 1 : 0)
|
||||||
|
let sheetFullyPresented = animator.fractionComplete == (animator.isReversed ? 0 : 1)
|
||||||
|
|
||||||
|
if !isPresented && sheetFullyDismissed ||
|
||||||
|
isPresented && sheetFullyPresented ||
|
||||||
|
alreadyAnimating {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
animator.pauseAnimation()
|
||||||
|
animator.isReversed = !isPresented
|
||||||
|
animator.continueAnimation(
|
||||||
|
withTimingParameters: isPresented
|
||||||
|
? easeOutCubic
|
||||||
|
: UICubicTimingParameters(animationCurve: .easeIn),
|
||||||
|
durationFactor: 1 - animator.fractionComplete
|
||||||
|
)
|
||||||
|
handleVisibility()
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleVisibility() {
|
||||||
|
if animator.isReversed {
|
||||||
|
task = Task {
|
||||||
|
do {
|
||||||
|
let sleepDuration = UInt64(sheetAnimationDuration * Double(NSEC_PER_SEC))
|
||||||
|
try await Task.sleep(nanoseconds: sleepDuration)
|
||||||
|
view.isHidden = true
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
task?.cancel()
|
||||||
|
task = nil
|
||||||
|
view.isHidden = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
view.isHidden = true
|
||||||
|
view.backgroundColor = .clear
|
||||||
|
view.addGestureRecognizer(
|
||||||
|
UITapGestureRecognizer(target: self, action: #selector(tap(gesture:)))
|
||||||
|
)
|
||||||
|
addChild(hostingController)
|
||||||
|
hostingController.didMove(toParent: self)
|
||||||
|
if let sheet = hostingController.view {
|
||||||
|
sheet.isHidden = true
|
||||||
|
sheet.clipsToBounds = true
|
||||||
|
sheet.layer.cornerRadius = 10
|
||||||
|
sheet.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner]
|
||||||
|
sheet.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(pan(gesture:))))
|
||||||
|
sheet.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
view.addSubview(sheet)
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
hostingController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||||
|
hostingController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||||
|
hostingController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidAppear(_ animated: Bool) {
|
||||||
|
// Ensures animations are only setup once
|
||||||
|
// on some iOS version `viewDidAppear` can get called on each state change.
|
||||||
|
if hostingController.view.isHidden {
|
||||||
|
hostingController.view.transform = CGAffineTransform(translationX: 0, y: self.sheetHeight)
|
||||||
|
hostingController.view.isHidden = false
|
||||||
|
animator.pausesOnCompletion = true
|
||||||
|
animator.addAnimations {
|
||||||
|
self.hostingController.view.transform = .identity
|
||||||
|
self.view.backgroundColor = UIColor {
|
||||||
|
switch $0.userInterfaceStyle {
|
||||||
|
case .dark: .black.withAlphaComponent(0.290)
|
||||||
|
default: .black.withAlphaComponent(0.121)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
animator.startAnimation()
|
||||||
|
animator.pauseAnimation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
func pan(gesture: UIPanGestureRecognizer) {
|
||||||
|
switch gesture.state {
|
||||||
|
case .began:
|
||||||
|
animator.isReversed = false
|
||||||
|
animator.pauseAnimation()
|
||||||
|
retainedFraction = animator.fractionComplete
|
||||||
|
case .changed:
|
||||||
|
animator.fractionComplete = retainedFraction - gesture.translation(in: view).y / sheetHeight
|
||||||
|
case .ended, .cancelled:
|
||||||
|
let velocity = gesture.velocity(in: view).y
|
||||||
|
animator.isReversed = (velocity - (animator.fractionComplete - 0.5) * 100).sign == .plus
|
||||||
|
let defaultVelocity = sheetHeight / sheetAnimationDuration
|
||||||
|
let fractionRemaining = 1 - animator.fractionComplete
|
||||||
|
let durationFactor = min(max(fractionRemaining / (abs(velocity) / defaultVelocity), 0.5), 1)
|
||||||
|
animator.continueAnimation(withTimingParameters: nil, durationFactor: durationFactor * fractionRemaining)
|
||||||
|
handleVisibility()
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + sheetAnimationDuration) {
|
||||||
|
self.representer.isPresented = !self.animator.isReversed
|
||||||
|
}
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
func tap(gesture: UITapGestureRecognizer) {
|
||||||
|
switch gesture.state {
|
||||||
|
case .ended:
|
||||||
|
if gesture.location(in: view).y < view.frame.height - sheetHeight {
|
||||||
|
representer.isPresented = false
|
||||||
|
}
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct StickyScrollView<Content: View>: UIViewRepresentable {
|
struct StickyScrollView<Content: View>: UIViewRepresentable {
|
||||||
|
@Binding var resetScroll: ResetScrollAction
|
||||||
@ViewBuilder let content: () -> Content
|
@ViewBuilder let content: () -> Content
|
||||||
|
|
||||||
func makeUIView(context: Context) -> UIScrollView {
|
func makeUIView(context: Context) -> UIScrollView {
|
||||||
@@ -18,6 +19,9 @@ struct StickyScrollView<Content: View>: UIViewRepresentable {
|
|||||||
sv.showsHorizontalScrollIndicator = false
|
sv.showsHorizontalScrollIndicator = false
|
||||||
sv.addSubview(hc.view)
|
sv.addSubview(hc.view)
|
||||||
sv.delegate = context.coordinator
|
sv.delegate = context.coordinator
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
resetScroll = ResetScrollAction { sv.setContentOffset(.zero, animated: false) }
|
||||||
|
}
|
||||||
return sv
|
return sv
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,3 +54,8 @@ struct StickyScrollView<Content: View>: UIViewRepresentable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ResetScrollAction {
|
||||||
|
var action = { }
|
||||||
|
func callAsFunction() { action() }
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ struct UserWallpaperEditor: View {
|
|||||||
@State var themeModeOverride: ThemeModeOverride
|
@State var themeModeOverride: ThemeModeOverride
|
||||||
@State var applyToMode: DefaultThemeMode?
|
@State var applyToMode: DefaultThemeMode?
|
||||||
@State var showMore: Bool = false
|
@State var showMore: Bool = false
|
||||||
|
@State var showFileImporter: Bool = false
|
||||||
@Binding var globalThemeUsed: Bool
|
@Binding var globalThemeUsed: Bool
|
||||||
var save: (DefaultThemeMode?, ThemeModeOverride?) async -> Void
|
var save: (DefaultThemeMode?, ThemeModeOverride?) async -> Void
|
||||||
|
|
||||||
@@ -125,24 +126,27 @@ struct UserWallpaperEditor: View {
|
|||||||
|
|
||||||
CustomizeThemeColorsSection(editColor: { name in editColor(name, theme) })
|
CustomizeThemeColorsSection(editColor: { name in editColor(name, theme) })
|
||||||
|
|
||||||
ImportExportThemeSection(perChat: nil, perUser: ChatModel.shared.currentUser?.uiThemes) { imported in
|
ImportExportThemeSection(showFileImporter: $showFileImporter, perChat: nil, perUser: ChatModel.shared.currentUser?.uiThemes)
|
||||||
let importedFromString = imported.wallpaper?.importFromString()
|
|
||||||
let importedType = importedFromString?.toAppWallpaper().type
|
|
||||||
let currentTheme = ThemeManager.currentColors(nil, nil, nil, themeOverridesDefault.get())
|
|
||||||
let type: WallpaperType? = if importedType?.sameType(currentTheme.wallpaper.type) == true { nil } else { importedType }
|
|
||||||
let colors = ThemeManager.currentThemeOverridesForExport(type, nil, nil).colors
|
|
||||||
let res = ThemeModeOverride(mode: imported.base.mode, colors: imported.colors, wallpaper: importedFromString).removeSameColors(imported.base, colorsToCompare: colors)
|
|
||||||
Task {
|
|
||||||
await MainActor.run {
|
|
||||||
themeModeOverride = res
|
|
||||||
}
|
|
||||||
await save(applyToMode, res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
AdvancedSettingsButton(theme.colors.primary) { showMore = true }
|
AdvancedSettingsButton(theme.colors.primary) { showMore = true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.modifier(
|
||||||
|
ThemeImporter(isPresented: $showFileImporter) { imported in
|
||||||
|
let importedFromString = imported.wallpaper?.importFromString()
|
||||||
|
let importedType = importedFromString?.toAppWallpaper().type
|
||||||
|
let currentTheme = ThemeManager.currentColors(nil, nil, nil, themeOverridesDefault.get())
|
||||||
|
let type: WallpaperType? = if importedType?.sameType(currentTheme.wallpaper.type) == true { nil } else { importedType }
|
||||||
|
let colors = ThemeManager.currentThemeOverridesForExport(type, nil, nil).colors
|
||||||
|
let res = ThemeModeOverride(mode: imported.base.mode, colors: imported.colors, wallpaper: importedFromString).removeSameColors(imported.base, colorsToCompare: colors)
|
||||||
|
Task {
|
||||||
|
await MainActor.run {
|
||||||
|
themeModeOverride = res
|
||||||
|
}
|
||||||
|
await save(applyToMode, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func onTypeCopyFromSameTheme(_ type: WallpaperType?) -> Bool {
|
private func onTypeCopyFromSameTheme(_ type: WallpaperType?) -> Bool {
|
||||||
@@ -216,6 +220,7 @@ struct ChatWallpaperEditor: View {
|
|||||||
@State var themeModeOverride: ThemeModeOverride
|
@State var themeModeOverride: ThemeModeOverride
|
||||||
@State var applyToMode: DefaultThemeMode?
|
@State var applyToMode: DefaultThemeMode?
|
||||||
@State var showMore: Bool = false
|
@State var showMore: Bool = false
|
||||||
|
@State var showFileImporter: Bool = false
|
||||||
@Binding var globalThemeUsed: Bool
|
@Binding var globalThemeUsed: Bool
|
||||||
var save: (DefaultThemeMode?, ThemeModeOverride?) async -> Void
|
var save: (DefaultThemeMode?, ThemeModeOverride?) async -> Void
|
||||||
|
|
||||||
@@ -328,24 +333,27 @@ struct ChatWallpaperEditor: View {
|
|||||||
|
|
||||||
CustomizeThemeColorsSection(editColor: editColor)
|
CustomizeThemeColorsSection(editColor: editColor)
|
||||||
|
|
||||||
ImportExportThemeSection(perChat: themeModeOverride, perUser: ChatModel.shared.currentUser?.uiThemes) { imported in
|
ImportExportThemeSection(showFileImporter: $showFileImporter, perChat: themeModeOverride, perUser: ChatModel.shared.currentUser?.uiThemes)
|
||||||
let importedFromString = imported.wallpaper?.importFromString()
|
|
||||||
let importedType = importedFromString?.toAppWallpaper().type
|
|
||||||
let currentTheme = ThemeManager.currentColors(nil, nil, ChatModel.shared.currentUser?.uiThemes, themeOverridesDefault.get())
|
|
||||||
let type: WallpaperType? = if importedType?.sameType(currentTheme.wallpaper.type) == true { nil } else { importedType }
|
|
||||||
let colors = ThemeManager.currentThemeOverridesForExport(type, nil, ChatModel.shared.currentUser?.uiThemes).colors
|
|
||||||
let res = ThemeModeOverride(mode: imported.base.mode, colors: imported.colors, wallpaper: importedFromString).removeSameColors(imported.base, colorsToCompare: colors)
|
|
||||||
Task {
|
|
||||||
await MainActor.run {
|
|
||||||
themeModeOverride = res
|
|
||||||
}
|
|
||||||
await save(applyToMode, res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
AdvancedSettingsButton(theme.colors.primary) { showMore = true }
|
AdvancedSettingsButton(theme.colors.primary) { showMore = true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.modifier(
|
||||||
|
ThemeImporter(isPresented: $showFileImporter) { imported in
|
||||||
|
let importedFromString = imported.wallpaper?.importFromString()
|
||||||
|
let importedType = importedFromString?.toAppWallpaper().type
|
||||||
|
let currentTheme = ThemeManager.currentColors(nil, nil, ChatModel.shared.currentUser?.uiThemes, themeOverridesDefault.get())
|
||||||
|
let type: WallpaperType? = if importedType?.sameType(currentTheme.wallpaper.type) == true { nil } else { importedType }
|
||||||
|
let colors = ThemeManager.currentThemeOverridesForExport(type, nil, ChatModel.shared.currentUser?.uiThemes).colors
|
||||||
|
let res = ThemeModeOverride(mode: imported.base.mode, colors: imported.colors, wallpaper: importedFromString).removeSameColors(imported.base, colorsToCompare: colors)
|
||||||
|
Task {
|
||||||
|
await MainActor.run {
|
||||||
|
themeModeOverride = res
|
||||||
|
}
|
||||||
|
await save(applyToMode, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func onTypeCopyFromSameTheme(_ type: WallpaperType?) -> Bool {
|
private func onTypeCopyFromSameTheme(_ type: WallpaperType?) -> Bool {
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// UserDefault.swift
|
||||||
|
// SimpleX (iOS)
|
||||||
|
//
|
||||||
|
// Created by user on 14/10/2024.
|
||||||
|
// Copyright © 2024 SimpleX Chat. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
@propertyWrapper
|
||||||
|
public struct UserDefault<Value: Equatable>: DynamicProperty {
|
||||||
|
@StateObject private var observer = UserDefaultObserver()
|
||||||
|
let initialValue: Value
|
||||||
|
let key: String
|
||||||
|
let store: UserDefaults
|
||||||
|
|
||||||
|
public init(
|
||||||
|
wrappedValue: Value,
|
||||||
|
_ key: String,
|
||||||
|
store: UserDefaults = .standard
|
||||||
|
) {
|
||||||
|
self.initialValue = wrappedValue
|
||||||
|
self.key = key
|
||||||
|
self.store = store
|
||||||
|
}
|
||||||
|
|
||||||
|
public var wrappedValue: Value {
|
||||||
|
get {
|
||||||
|
// Observer can only be accessed after the property wrapper is installed in view (runtime exception)
|
||||||
|
observer.subscribe(to: key)
|
||||||
|
return store.object(forKey: key) as? Value ?? initialValue
|
||||||
|
}
|
||||||
|
nonmutating set {
|
||||||
|
store.set(newValue, forKey: key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class UserDefaultObserver: ObservableObject {
|
||||||
|
private var subscribed = false
|
||||||
|
|
||||||
|
func subscribe(to key: String) {
|
||||||
|
if !subscribed {
|
||||||
|
NotificationCenter.default.addObserver(
|
||||||
|
self,
|
||||||
|
selector: #selector(userDefaultsDidChange),
|
||||||
|
name: UserDefaults.didChangeNotification,
|
||||||
|
object: nil
|
||||||
|
)
|
||||||
|
subscribed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
private func userDefaultsDidChange(_ notification: Notification) {
|
||||||
|
Task { @MainActor in objectWillChange.send() }
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit { NotificationCenter.default.removeObserver(self) }
|
||||||
|
}
|
||||||
@@ -137,10 +137,13 @@ struct AddGroupView: View {
|
|||||||
createInvalidNameAlert(mkValidName(profile.displayName), $profile.displayName)
|
createInvalidNameAlert(mkValidName(profile.displayName), $profile.displayName)
|
||||||
}
|
}
|
||||||
.onChange(of: chosenImage) { image in
|
.onChange(of: chosenImage) { image in
|
||||||
if let image = image {
|
Task {
|
||||||
profile.image = resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500)
|
let resized: String? = if let image {
|
||||||
} else {
|
await resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500)
|
||||||
profile.image = nil
|
} else {
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
await MainActor.run { profile.image = resized }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.modifier(ThemedBackground(grouped: true))
|
.modifier(ThemedBackground(grouped: true))
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ enum ContactType: Int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct NewChatMenuButton: View {
|
struct NewChatMenuButton: View {
|
||||||
@EnvironmentObject var chatModel: ChatModel
|
// do not use chatModel here because it prevents showing AddGroupMembersView after group creation and QR code after link creation on iOS 16
|
||||||
|
// @EnvironmentObject var chatModel: ChatModel
|
||||||
@State private var showNewChatSheet = false
|
@State private var showNewChatSheet = false
|
||||||
@State private var alert: SomeAlert? = nil
|
@State private var alert: SomeAlert? = nil
|
||||||
@State private var pendingConnection: PendingContactConnection? = nil
|
@State private var pendingConnection: PendingContactConnection? = nil
|
||||||
@@ -32,7 +33,7 @@ struct NewChatMenuButton: View {
|
|||||||
NewChatSheet(pendingConnection: $pendingConnection)
|
NewChatSheet(pendingConnection: $pendingConnection)
|
||||||
.environment(\EnvironmentValues.refresh as! WritableKeyPath<EnvironmentValues, RefreshAction?>, nil)
|
.environment(\EnvironmentValues.refresh as! WritableKeyPath<EnvironmentValues, RefreshAction?>, nil)
|
||||||
.onDisappear {
|
.onDisappear {
|
||||||
alert = cleanupPendingConnection(chatModel: chatModel, contactConnection: pendingConnection)
|
alert = cleanupPendingConnection(contactConnection: pendingConnection)
|
||||||
pendingConnection = nil
|
pendingConnection = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,10 +45,10 @@ enum NewChatOption: Identifiable {
|
|||||||
var id: Self { self }
|
var id: Self { self }
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanupPendingConnection(chatModel: ChatModel, contactConnection: PendingContactConnection?) -> SomeAlert? {
|
func cleanupPendingConnection(contactConnection: PendingContactConnection?) -> SomeAlert? {
|
||||||
var alert: SomeAlert? = nil
|
var alert: SomeAlert? = nil
|
||||||
|
|
||||||
if !(chatModel.showingInvitation?.connChatUsed ?? true),
|
if !(ChatModel.shared.showingInvitation?.connChatUsed ?? true),
|
||||||
let conn = contactConnection {
|
let conn = contactConnection {
|
||||||
alert = SomeAlert(
|
alert = SomeAlert(
|
||||||
alert: Alert(
|
alert: Alert(
|
||||||
@@ -68,7 +68,7 @@ func cleanupPendingConnection(chatModel: ChatModel, contactConnection: PendingCo
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
chatModel.showingInvitation = nil
|
ChatModel.shared.showingInvitation = nil
|
||||||
|
|
||||||
return alert
|
return alert
|
||||||
}
|
}
|
||||||
@@ -97,6 +97,11 @@ struct NewChatView: View {
|
|||||||
}
|
}
|
||||||
.pickerStyle(.segmented)
|
.pickerStyle(.segmented)
|
||||||
.padding()
|
.padding()
|
||||||
|
.onChange(of: $selection.wrappedValue) { opt in
|
||||||
|
if opt == NewChatOption.connect {
|
||||||
|
showQRCodeScanner = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VStack {
|
VStack {
|
||||||
// it seems there's a bug in iOS 15 if several views in switch (or if-else) statement have different transitions
|
// it seems there's a bug in iOS 15 if several views in switch (or if-else) statement have different transitions
|
||||||
@@ -152,7 +157,7 @@ struct NewChatView: View {
|
|||||||
}
|
}
|
||||||
.onDisappear {
|
.onDisappear {
|
||||||
if !choosingProfile {
|
if !choosingProfile {
|
||||||
parentAlert = cleanupPendingConnection(chatModel: m, contactConnection: contactConnection)
|
parentAlert = cleanupPendingConnection(contactConnection: contactConnection)
|
||||||
contactConnection = nil
|
contactConnection = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,7 +246,6 @@ private struct InviteView: View {
|
|||||||
@Binding var choosingProfile: Bool
|
@Binding var choosingProfile: Bool
|
||||||
|
|
||||||
@AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false
|
@AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false
|
||||||
@State private var showSettings: Bool = false
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
List {
|
List {
|
||||||
@@ -693,6 +697,7 @@ struct ScannerInView: View {
|
|||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
.foregroundColor(Color.clear)
|
.foregroundColor(Color.clear)
|
||||||
switch cameraAuthorizationStatus {
|
switch cameraAuthorizationStatus {
|
||||||
|
case .authorized, nil: EmptyView()
|
||||||
case .restricted: Text("Camera not available")
|
case .restricted: Text("Camera not available")
|
||||||
case .denied: Label("Enable camera access", systemImage: "camera")
|
case .denied: Label("Enable camera access", systemImage: "camera")
|
||||||
default: Label("Tap to scan", systemImage: "qrcode")
|
default: Label("Tap to scan", systemImage: "qrcode")
|
||||||
@@ -712,21 +717,26 @@ struct ScannerInView: View {
|
|||||||
.disabled(cameraAuthorizationStatus == .restricted)
|
.disabled(cameraAuthorizationStatus == .restricted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onAppear {
|
.task {
|
||||||
let status = AVCaptureDevice.authorizationStatus(for: .video)
|
let status = AVCaptureDevice.authorizationStatus(for: .video)
|
||||||
cameraAuthorizationStatus = status
|
cameraAuthorizationStatus = status
|
||||||
if showQRCodeScanner {
|
if showQRCodeScanner {
|
||||||
switch status {
|
switch status {
|
||||||
case .notDetermined: askCameraAuthorization()
|
case .notDetermined: await askCameraAuthorizationAsync()
|
||||||
case .restricted: showQRCodeScanner = false
|
case .restricted: showQRCodeScanner = false
|
||||||
case .denied: showQRCodeScanner = false
|
case .denied: showQRCodeScanner = false
|
||||||
case .authorized: ()
|
case .authorized: ()
|
||||||
@unknown default: askCameraAuthorization()
|
@unknown default: await askCameraAuthorizationAsync()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func askCameraAuthorizationAsync() async {
|
||||||
|
await AVCaptureDevice.requestAccess(for: .video)
|
||||||
|
cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
|
||||||
|
}
|
||||||
|
|
||||||
func askCameraAuthorization(_ cb: (() -> Void)? = nil) {
|
func askCameraAuthorization(_ cb: (() -> Void)? = nil) {
|
||||||
AVCaptureDevice.requestAccess(for: .video) { allowed in
|
AVCaptureDevice.requestAccess(for: .video) { allowed in
|
||||||
cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
|
cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
|
||||||
|
|||||||
@@ -49,34 +49,34 @@ struct QRCode: View {
|
|||||||
ZStack {
|
ZStack {
|
||||||
if let image = image {
|
if let image = image {
|
||||||
qrCodeImage(image)
|
qrCodeImage(image)
|
||||||
}
|
GeometryReader { geo in
|
||||||
GeometryReader { geo in
|
ZStack {
|
||||||
ZStack {
|
if withLogo {
|
||||||
if withLogo {
|
let w = geo.size.width
|
||||||
let w = geo.size.width
|
Image("icon-light")
|
||||||
Image("icon-light")
|
.resizable()
|
||||||
.resizable()
|
.scaledToFit()
|
||||||
.scaledToFit()
|
.frame(width: w * 0.16, height: w * 0.16)
|
||||||
.frame(width: w * 0.16, height: w * 0.16)
|
.frame(width: w * 0.165, height: w * 0.165)
|
||||||
.frame(width: w * 0.165, height: w * 0.165)
|
.background(.white)
|
||||||
.background(.white)
|
.clipShape(Circle())
|
||||||
.clipShape(Circle())
|
}
|
||||||
}
|
}
|
||||||
}
|
.onAppear {
|
||||||
.onAppear {
|
makeScreenshotFunc = {
|
||||||
makeScreenshotFunc = {
|
let size = CGSizeMake(1024 / UIScreen.main.scale, 1024 / UIScreen.main.scale)
|
||||||
let size = CGSizeMake(1024 / UIScreen.main.scale, 1024 / UIScreen.main.scale)
|
showShareSheet(items: [makeScreenshot(geo.frame(in: .local).origin, size)])
|
||||||
showShareSheet(items: [makeScreenshot(geo.frame(in: .local).origin, size)])
|
onShare?()
|
||||||
onShare?()
|
}
|
||||||
}
|
}
|
||||||
|
.frame(width: geo.size.width, height: geo.size.height)
|
||||||
}
|
}
|
||||||
.frame(width: geo.size.width, height: geo.size.height)
|
} else {
|
||||||
|
Color.clear.aspectRatio(1, contentMode: .fit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onTapGesture(perform: makeScreenshotFunc)
|
.onTapGesture(perform: makeScreenshotFunc)
|
||||||
.onAppear {
|
.task { image = await generateImage(uri, tintColor: tintColor) }
|
||||||
image = image ?? generateImage(uri, tintColor: tintColor)
|
|
||||||
}
|
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ private func qrCodeImage(_ image: UIImage) -> some View {
|
|||||||
.textSelection(.enabled)
|
.textSelection(.enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func generateImage(_ uri: String, tintColor: UIColor) -> UIImage? {
|
private func generateImage(_ uri: String, tintColor: UIColor) async -> UIImage? {
|
||||||
let context = CIContext()
|
let context = CIContext()
|
||||||
let filter = CIFilter.qrCodeGenerator()
|
let filter = CIFilter.qrCodeGenerator()
|
||||||
filter.message = Data(uri.utf8)
|
filter.message = Data(uri.utf8)
|
||||||
|
|||||||
@@ -467,6 +467,39 @@ private let versionDescriptions: [VersionDescription] = [
|
|||||||
)
|
)
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
VersionDescription(
|
||||||
|
version: "v6.1",
|
||||||
|
post: URL(string: "https://simplex.chat/blog/20241014-simplex-network-v6-1-security-review-better-calls-user-experience.html"),
|
||||||
|
features: [
|
||||||
|
FeatureDescription(
|
||||||
|
icon: "checkmark.shield",
|
||||||
|
title: "Better security ✅",
|
||||||
|
description: "SimpleX protocols reviewed by Trail of Bits."
|
||||||
|
),
|
||||||
|
FeatureDescription(
|
||||||
|
icon: "video",
|
||||||
|
title: "Better calls",
|
||||||
|
description: "Switch audio and video during the call."
|
||||||
|
),
|
||||||
|
FeatureDescription(
|
||||||
|
icon: "bolt",
|
||||||
|
title: "Better notifications",
|
||||||
|
description: "Improved delivery, reduced traffic usage.\nMore improvements are coming soon!"
|
||||||
|
),
|
||||||
|
FeatureDescription(
|
||||||
|
icon: nil,
|
||||||
|
title: "Better user experience",
|
||||||
|
description: nil,
|
||||||
|
subfeatures: [
|
||||||
|
("link", "Switch chat profile for 1-time invitations."),
|
||||||
|
("message", "Customizable message shape."),
|
||||||
|
("calendar", "Better message dates."),
|
||||||
|
("arrowshape.turn.up.right", "Forward up to 20 messages at once."),
|
||||||
|
("flag", "Delete or moderate up to 200 messages.")
|
||||||
|
]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
private let lastVersion = versionDescriptions.last!.version
|
private let lastVersion = versionDescriptions.last!.version
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ struct ConnectDesktopView: View {
|
|||||||
@EnvironmentObject var m: ChatModel
|
@EnvironmentObject var m: ChatModel
|
||||||
@EnvironmentObject var theme: AppTheme
|
@EnvironmentObject var theme: AppTheme
|
||||||
@Environment(\.dismiss) var dismiss: DismissAction
|
@Environment(\.dismiss) var dismiss: DismissAction
|
||||||
var viaSettings = false
|
|
||||||
@AppStorage(DEFAULT_DEVICE_NAME_FOR_REMOTE_ACCESS) private var deviceName = UIDevice.current.name
|
@AppStorage(DEFAULT_DEVICE_NAME_FOR_REMOTE_ACCESS) private var deviceName = UIDevice.current.name
|
||||||
@AppStorage(DEFAULT_CONFIRM_REMOTE_SESSIONS) private var confirmRemoteSessions = false
|
@AppStorage(DEFAULT_CONFIRM_REMOTE_SESSIONS) private var confirmRemoteSessions = false
|
||||||
@AppStorage(DEFAULT_CONNECT_REMOTE_VIA_MULTICAST) private var connectRemoteViaMulticast = true
|
@AppStorage(DEFAULT_CONNECT_REMOTE_VIA_MULTICAST) private var connectRemoteViaMulticast = true
|
||||||
@@ -57,16 +56,6 @@ struct ConnectDesktopView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if viaSettings {
|
|
||||||
viewBody
|
|
||||||
} else {
|
|
||||||
NavigationView {
|
|
||||||
viewBody
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var viewBody: some View {
|
|
||||||
Group {
|
Group {
|
||||||
let discovery = m.remoteCtrlSession?.discovery
|
let discovery = m.remoteCtrlSession?.discovery
|
||||||
if discovery == true || (discovery == nil && !showConnectScreen) {
|
if discovery == true || (discovery == nil && !showConnectScreen) {
|
||||||
|
|||||||
@@ -105,7 +105,12 @@ struct TerminalView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationViewStyle(.stack)
|
.navigationViewStyle(.stack)
|
||||||
.navigationTitle("Chat console")
|
.toolbar {
|
||||||
|
// Redaction broken for `.navigationTitle` - using a toolbar item instead.
|
||||||
|
ToolbarItem(placement: .principal) {
|
||||||
|
Text("Chat console").font(.headline)
|
||||||
|
}
|
||||||
|
}
|
||||||
.modifier(ThemedBackground())
|
.modifier(ThemedBackground())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ extension AppSettings {
|
|||||||
profileImageCornerRadiusGroupDefault.set(val)
|
profileImageCornerRadiusGroupDefault.set(val)
|
||||||
def.setValue(val, forKey: DEFAULT_PROFILE_IMAGE_CORNER_RADIUS)
|
def.setValue(val, forKey: DEFAULT_PROFILE_IMAGE_CORNER_RADIUS)
|
||||||
}
|
}
|
||||||
|
if let val = uiChatItemRoundness { def.setValue(val, forKey: DEFAULT_CHAT_ITEM_ROUNDNESS)}
|
||||||
|
if let val = uiChatItemTail { def.setValue(val, forKey: DEFAULT_CHAT_ITEM_TAIL)}
|
||||||
if let val = uiColorScheme { currentThemeDefault.set(val) }
|
if let val = uiColorScheme { currentThemeDefault.set(val) }
|
||||||
if let val = uiDarkColorScheme { systemDarkThemeDefault.set(val) }
|
if let val = uiDarkColorScheme { systemDarkThemeDefault.set(val) }
|
||||||
if let val = uiCurrentThemeIds { currentThemeIdsDefault.set(val) }
|
if let val = uiCurrentThemeIds { currentThemeIdsDefault.set(val) }
|
||||||
@@ -91,6 +93,8 @@ extension AppSettings {
|
|||||||
c.iosCallKitEnabled = callKitEnabledGroupDefault.get()
|
c.iosCallKitEnabled = callKitEnabledGroupDefault.get()
|
||||||
c.iosCallKitCallsInRecents = def.bool(forKey: DEFAULT_CALL_KIT_CALLS_IN_RECENTS)
|
c.iosCallKitCallsInRecents = def.bool(forKey: DEFAULT_CALL_KIT_CALLS_IN_RECENTS)
|
||||||
c.uiProfileImageCornerRadius = def.double(forKey: DEFAULT_PROFILE_IMAGE_CORNER_RADIUS)
|
c.uiProfileImageCornerRadius = def.double(forKey: DEFAULT_PROFILE_IMAGE_CORNER_RADIUS)
|
||||||
|
c.uiChatItemRoundness = def.double(forKey: DEFAULT_CHAT_ITEM_ROUNDNESS)
|
||||||
|
c.uiChatItemTail = def.bool(forKey: DEFAULT_CHAT_ITEM_TAIL)
|
||||||
c.uiColorScheme = currentThemeDefault.get()
|
c.uiColorScheme = currentThemeDefault.get()
|
||||||
c.uiDarkColorScheme = systemDarkThemeDefault.get()
|
c.uiDarkColorScheme = systemDarkThemeDefault.get()
|
||||||
c.uiCurrentThemeIds = currentThemeIdsDefault.get()
|
c.uiCurrentThemeIds = currentThemeIdsDefault.get()
|
||||||
|
|||||||
@@ -367,13 +367,13 @@ struct ChatThemePreview: View {
|
|||||||
let alice = ChatItem.getSample(1, CIDirection.directRcv, Date.now, NSLocalizedString("Good afternoon!", comment: "message preview"))
|
let alice = ChatItem.getSample(1, CIDirection.directRcv, Date.now, NSLocalizedString("Good afternoon!", comment: "message preview"))
|
||||||
let bob = ChatItem.getSample(2, CIDirection.directSnd, Date.now, NSLocalizedString("Good morning!", comment: "message preview"), quotedItem: CIQuote.getSample(alice.id, alice.meta.itemTs, alice.content.text, chatDir: alice.chatDir))
|
let bob = ChatItem.getSample(2, CIDirection.directSnd, Date.now, NSLocalizedString("Good morning!", comment: "message preview"), quotedItem: CIQuote.getSample(alice.id, alice.meta.itemTs, alice.content.text, chatDir: alice.chatDir))
|
||||||
HStack {
|
HStack {
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: alice, revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: alice)
|
||||||
.modifier(ChatItemClipped(alice, tailVisible: true))
|
.modifier(ChatItemClipped(alice, tailVisible: true))
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
ChatItemView(chat: Chat.sampleData, chatItem: bob, revealed: Binding.constant(false))
|
ChatItemView(chat: Chat.sampleData, chatItem: bob)
|
||||||
.modifier(ChatItemClipped(bob, tailVisible: true))
|
.modifier(ChatItemClipped(bob, tailVisible: true))
|
||||||
.frame(alignment: .trailing)
|
.frame(alignment: .trailing)
|
||||||
}
|
}
|
||||||
@@ -583,11 +583,14 @@ struct CustomizeThemeView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImportExportThemeSection(perChat: nil, perUser: nil, save: { theme in
|
ImportExportThemeSection(showFileImporter: $showFileImporter, perChat: nil, perUser: nil)
|
||||||
|
}
|
||||||
|
.modifier(
|
||||||
|
ThemeImporter(isPresented: $showFileImporter) { theme in
|
||||||
ThemeManager.saveAndApplyThemeOverrides(theme)
|
ThemeManager.saveAndApplyThemeOverrides(theme)
|
||||||
saveThemeToDatabase(nil)
|
saveThemeToDatabase(nil)
|
||||||
})
|
}
|
||||||
}
|
)
|
||||||
/// When changing app theme, user overrides are hidden. User overrides will be returned back after closing Appearance screen, see ThemeDestinationPicker()
|
/// When changing app theme, user overrides are hidden. User overrides will be returned back after closing Appearance screen, see ThemeDestinationPicker()
|
||||||
.interactiveDismissDisabled(true)
|
.interactiveDismissDisabled(true)
|
||||||
}
|
}
|
||||||
@@ -595,10 +598,9 @@ struct CustomizeThemeView: View {
|
|||||||
|
|
||||||
struct ImportExportThemeSection: View {
|
struct ImportExportThemeSection: View {
|
||||||
@EnvironmentObject var theme: AppTheme
|
@EnvironmentObject var theme: AppTheme
|
||||||
|
@Binding var showFileImporter: Bool
|
||||||
var perChat: ThemeModeOverride?
|
var perChat: ThemeModeOverride?
|
||||||
var perUser: ThemeModeOverrides?
|
var perUser: ThemeModeOverrides?
|
||||||
var save: (ThemeOverrides) -> Void
|
|
||||||
@State private var showFileImporter = false
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Section {
|
Section {
|
||||||
@@ -626,39 +628,47 @@ struct ImportExportThemeSection: View {
|
|||||||
} label: {
|
} label: {
|
||||||
Text("Import theme").foregroundColor(theme.colors.primary)
|
Text("Import theme").foregroundColor(theme.colors.primary)
|
||||||
}
|
}
|
||||||
.fileImporter(
|
}
|
||||||
isPresented: $showFileImporter,
|
}
|
||||||
allowedContentTypes: [.data/*.plainText*/],
|
}
|
||||||
allowsMultipleSelection: false
|
|
||||||
) { result in
|
struct ThemeImporter: ViewModifier {
|
||||||
if case let .success(files) = result, let fileURL = files.first {
|
@Binding var isPresented: Bool
|
||||||
do {
|
var save: (ThemeOverrides) -> Void
|
||||||
var fileSize: Int? = nil
|
|
||||||
if fileURL.startAccessingSecurityScopedResource() {
|
func body(content: Content) -> some View {
|
||||||
let resourceValues = try fileURL.resourceValues(forKeys: [.fileSizeKey])
|
content.fileImporter(
|
||||||
fileSize = resourceValues.fileSize
|
isPresented: $isPresented,
|
||||||
}
|
allowedContentTypes: [.data/*.plainText*/],
|
||||||
if let fileSize = fileSize,
|
allowsMultipleSelection: false
|
||||||
// Same as Android/desktop
|
) { result in
|
||||||
fileSize <= 5_500_000 {
|
if case let .success(files) = result, let fileURL = files.first {
|
||||||
if let string = try? String(contentsOf: fileURL, encoding: .utf8), let theme: ThemeOverrides = decodeYAML("themeId: \(UUID().uuidString)\n" + string) {
|
do {
|
||||||
save(theme)
|
var fileSize: Int? = nil
|
||||||
logger.error("Saved theme from file")
|
if fileURL.startAccessingSecurityScopedResource() {
|
||||||
} else {
|
let resourceValues = try fileURL.resourceValues(forKeys: [.fileSizeKey])
|
||||||
logger.error("Error decoding theme file")
|
fileSize = resourceValues.fileSize
|
||||||
}
|
|
||||||
fileURL.stopAccessingSecurityScopedResource()
|
|
||||||
} else {
|
|
||||||
fileURL.stopAccessingSecurityScopedResource()
|
|
||||||
let prettyMaxFileSize = ByteCountFormatter.string(fromByteCount: 5_500_000, countStyle: .binary)
|
|
||||||
AlertManager.shared.showAlertMsg(
|
|
||||||
title: "Large file!",
|
|
||||||
message: "Currently maximum supported file size is \(prettyMaxFileSize)."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
logger.error("Appearance fileImporter error \(error.localizedDescription)")
|
|
||||||
}
|
}
|
||||||
|
if let fileSize = fileSize,
|
||||||
|
// Same as Android/desktop
|
||||||
|
fileSize <= 5_500_000 {
|
||||||
|
if let string = try? String(contentsOf: fileURL, encoding: .utf8), let theme: ThemeOverrides = decodeYAML("themeId: \(UUID().uuidString)\n" + string) {
|
||||||
|
save(theme)
|
||||||
|
logger.error("Saved theme from file")
|
||||||
|
} else {
|
||||||
|
logger.error("Error decoding theme file")
|
||||||
|
}
|
||||||
|
fileURL.stopAccessingSecurityScopedResource()
|
||||||
|
} else {
|
||||||
|
fileURL.stopAccessingSecurityScopedResource()
|
||||||
|
let prettyMaxFileSize = ByteCountFormatter.string(fromByteCount: 5_500_000, countStyle: .binary)
|
||||||
|
AlertManager.shared.showAlertMsg(
|
||||||
|
title: "Large file!",
|
||||||
|
message: "Currently maximum supported file size is \(prettyMaxFileSize)."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
logger.error("Appearance fileImporter error \(error.localizedDescription)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-6
@@ -196,11 +196,14 @@ struct AdvancedNetworkSettings: View {
|
|||||||
if developerTools {
|
if developerTools {
|
||||||
Section {
|
Section {
|
||||||
Picker("Transport isolation", selection: $netCfg.sessionMode) {
|
Picker("Transport isolation", selection: $netCfg.sessionMode) {
|
||||||
ForEach(TransportSessionMode.values, id: \.self) { Text($0.text) }
|
let modes = TransportSessionMode.values.contains(netCfg.sessionMode)
|
||||||
|
? TransportSessionMode.values
|
||||||
|
: TransportSessionMode.values + [netCfg.sessionMode]
|
||||||
|
ForEach(modes, id: \.self) { Text($0.text) }
|
||||||
}
|
}
|
||||||
.frame(height: 36)
|
.frame(height: 36)
|
||||||
} footer: {
|
} footer: {
|
||||||
Text(sessionModeInfo(netCfg.sessionMode))
|
sessionModeInfo(netCfg.sessionMode)
|
||||||
.foregroundColor(theme.colors.secondary)
|
.foregroundColor(theme.colors.secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -353,10 +356,13 @@ struct AdvancedNetworkSettings: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func sessionModeInfo(_ mode: TransportSessionMode) -> LocalizedStringKey {
|
private func sessionModeInfo(_ mode: TransportSessionMode) -> Text {
|
||||||
switch mode {
|
let userMode = Text("A separate TCP connection will be used **for each chat profile you have in the app**.")
|
||||||
case .user: return "A separate TCP connection will be used **for each chat profile you have in the app**."
|
return switch mode {
|
||||||
case .entity: return "A separate TCP connection will be used **for each contact and group member**.\n**Please note**: if you have many connections, your battery and traffic consumption can be substantially higher and some connections may fail."
|
case .user: userMode
|
||||||
|
case .session: userMode + Text("\n") + Text("New SOCKS credentials will be used every time you start the app.")
|
||||||
|
case .server: userMode + Text("\n") + Text("New SOCKS credentials will be used for each server.")
|
||||||
|
case .entity: Text("A separate TCP connection will be used **for each contact and group member**.\n**Please note**: if you have many connections, your battery and traffic consumption can be substantially higher and some connections may fail.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,23 +257,18 @@ let networkProxyDefault: CodableDefault<NetworkProxy> = CodableDefault(defaults:
|
|||||||
|
|
||||||
struct SettingsView: View {
|
struct SettingsView: View {
|
||||||
@Environment(\.colorScheme) var colorScheme
|
@Environment(\.colorScheme) var colorScheme
|
||||||
|
@Environment(\.dismiss) var dismiss
|
||||||
@EnvironmentObject var chatModel: ChatModel
|
@EnvironmentObject var chatModel: ChatModel
|
||||||
@EnvironmentObject var sceneDelegate: SceneDelegate
|
@EnvironmentObject var sceneDelegate: SceneDelegate
|
||||||
@EnvironmentObject var theme: AppTheme
|
@EnvironmentObject var theme: AppTheme
|
||||||
@Binding var showSettings: Bool
|
|
||||||
@State private var showProgress: Bool = false
|
@State private var showProgress: Bool = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
NavigationView {
|
settingsView()
|
||||||
settingsView()
|
|
||||||
}
|
|
||||||
if showProgress {
|
if showProgress {
|
||||||
progressView()
|
progressView()
|
||||||
}
|
}
|
||||||
if let la = chatModel.laRequest {
|
|
||||||
LocalAuthView(authRequest: la)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,7 +331,12 @@ struct SettingsView: View {
|
|||||||
chatDatabaseRow()
|
chatDatabaseRow()
|
||||||
NavigationLink {
|
NavigationLink {
|
||||||
MigrateFromDevice(showProgressOnSettings: $showProgress)
|
MigrateFromDevice(showProgressOnSettings: $showProgress)
|
||||||
.navigationTitle("Migrate device")
|
.toolbar {
|
||||||
|
// Redaction broken for `.navigationTitle` - using a toolbar item instead.
|
||||||
|
ToolbarItem(placement: .principal) {
|
||||||
|
Text("Migrate device").font(.headline)
|
||||||
|
}
|
||||||
|
}
|
||||||
.modifier(ThemedBackground(grouped: true))
|
.modifier(ThemedBackground(grouped: true))
|
||||||
.navigationBarTitleDisplayMode(.large)
|
.navigationBarTitleDisplayMode(.large)
|
||||||
} label: {
|
} label: {
|
||||||
@@ -347,7 +347,7 @@ struct SettingsView: View {
|
|||||||
Section(header: Text("Help").foregroundColor(theme.colors.secondary)) {
|
Section(header: Text("Help").foregroundColor(theme.colors.secondary)) {
|
||||||
if let user = user {
|
if let user = user {
|
||||||
NavigationLink {
|
NavigationLink {
|
||||||
ChatHelp(showSettings: $showSettings)
|
ChatHelp(dismissSettingsSheet: dismiss)
|
||||||
.navigationTitle("Welcome \(user.displayName)!")
|
.navigationTitle("Welcome \(user.displayName)!")
|
||||||
.modifier(ThemedBackground())
|
.modifier(ThemedBackground())
|
||||||
.frame(maxHeight: .infinity, alignment: .top)
|
.frame(maxHeight: .infinity, alignment: .top)
|
||||||
@@ -372,7 +372,7 @@ struct SettingsView: View {
|
|||||||
}
|
}
|
||||||
settingsRow("number", color: theme.colors.secondary) {
|
settingsRow("number", color: theme.colors.secondary) {
|
||||||
Button("Send questions and ideas") {
|
Button("Send questions and ideas") {
|
||||||
showSettings = false
|
dismiss()
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
UIApplication.shared.open(simplexTeamURL)
|
UIApplication.shared.open(simplexTeamURL)
|
||||||
}
|
}
|
||||||
@@ -429,7 +429,7 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
private func chatDatabaseRow() -> some View {
|
private func chatDatabaseRow() -> some View {
|
||||||
NavigationLink {
|
NavigationLink {
|
||||||
DatabaseView(showSettings: $showSettings, chatItemTTL: chatModel.chatItemTTL)
|
DatabaseView(dismissSettingsSheet: dismiss, chatItemTTL: chatModel.chatItemTTL)
|
||||||
.navigationTitle("Your chat database")
|
.navigationTitle("Your chat database")
|
||||||
.modifier(ThemedBackground(grouped: true))
|
.modifier(ThemedBackground(grouped: true))
|
||||||
} label: {
|
} label: {
|
||||||
@@ -525,9 +525,7 @@ struct SettingsView_Previews: PreviewProvider {
|
|||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let chatModel = ChatModel()
|
let chatModel = ChatModel()
|
||||||
chatModel.currentUser = User.sampleData
|
chatModel.currentUser = User.sampleData
|
||||||
@State var showSettings = false
|
return SettingsView()
|
||||||
|
|
||||||
return SettingsView(showSettings: $showSettings)
|
|
||||||
.environmentObject(chatModel)
|
.environmentObject(chatModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,10 +94,13 @@ struct UserProfile: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onChange(of: chosenImage) { image in
|
.onChange(of: chosenImage) { image in
|
||||||
if let image {
|
Task {
|
||||||
profile.image = resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500)
|
let resized: String? = if let image {
|
||||||
} else {
|
await resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500)
|
||||||
profile.image = nil
|
} else {
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
await MainActor.run { profile.image = resized }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Modals
|
// Modals
|
||||||
|
|||||||
@@ -737,7 +737,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All profiles" xml:space="preserve">
|
<trans-unit id="All profiles" xml:space="preserve">
|
||||||
<source>All profiles</source>
|
<source>All profiles</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>profile dropdown</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||||
<source>All your contacts will remain connected.</source>
|
<source>All your contacts will remain connected.</source>
|
||||||
@@ -925,6 +925,10 @@
|
|||||||
<target>Кода за достъп до приложение се заменя с код за самоунищожение.</target>
|
<target>Кода за достъп до приложение се заменя с код за самоунищожение.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="App session" xml:space="preserve">
|
||||||
|
<source>App session</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="App version" xml:space="preserve">
|
<trans-unit id="App version" xml:space="preserve">
|
||||||
<source>App version</source>
|
<source>App version</source>
|
||||||
<target>Версия на приложението</target>
|
<target>Версия на приложението</target>
|
||||||
@@ -1055,11 +1059,19 @@
|
|||||||
<target>Лош хеш на съобщението</target>
|
<target>Лош хеш на съобщението</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better calls" xml:space="preserve">
|
||||||
|
<source>Better calls</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better groups" xml:space="preserve">
|
<trans-unit id="Better groups" xml:space="preserve">
|
||||||
<source>Better groups</source>
|
<source>Better groups</source>
|
||||||
<target>По-добри групи</target>
|
<target>По-добри групи</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better message dates." xml:space="preserve">
|
||||||
|
<source>Better message dates.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better messages" xml:space="preserve">
|
<trans-unit id="Better messages" xml:space="preserve">
|
||||||
<source>Better messages</source>
|
<source>Better messages</source>
|
||||||
<target>По-добри съобщения</target>
|
<target>По-добри съобщения</target>
|
||||||
@@ -1069,6 +1081,18 @@
|
|||||||
<source>Better networking</source>
|
<source>Better networking</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better notifications" xml:space="preserve">
|
||||||
|
<source>Better notifications</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||||
|
<source>Better security ✅</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better user experience" xml:space="preserve">
|
||||||
|
<source>Better user experience</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Black" xml:space="preserve">
|
<trans-unit id="Black" xml:space="preserve">
|
||||||
<source>Black</source>
|
<source>Black</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -1342,6 +1366,11 @@
|
|||||||
<source>Chat preferences were changed.</source>
|
<source>Chat preferences were changed.</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat profile" xml:space="preserve">
|
||||||
|
<source>Chat profile</source>
|
||||||
|
<target>Потребителски профил</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Chat theme" xml:space="preserve">
|
<trans-unit id="Chat theme" xml:space="preserve">
|
||||||
<source>Chat theme</source>
|
<source>Chat theme</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -1844,6 +1873,10 @@ This is your own one-time link!</source>
|
|||||||
<target>Персонализирано време</target>
|
<target>Персонализирано време</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Customizable message shape." xml:space="preserve">
|
||||||
|
<source>Customizable message shape.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Customize theme" xml:space="preserve">
|
<trans-unit id="Customize theme" xml:space="preserve">
|
||||||
<source>Customize theme</source>
|
<source>Customize theme</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -2133,6 +2166,10 @@ This is your own one-time link!</source>
|
|||||||
<target>Изтрий старата база данни?</target>
|
<target>Изтрий старата база данни?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Delete or moderate up to 200 messages." xml:space="preserve">
|
||||||
|
<source>Delete or moderate up to 200 messages.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
||||||
<source>Delete pending connection?</source>
|
<source>Delete pending connection?</source>
|
||||||
<target>Изтрий предстоящата връзка?</target>
|
<target>Изтрий предстоящата връзка?</target>
|
||||||
@@ -2934,7 +2971,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error switching profile!" xml:space="preserve">
|
<trans-unit id="Error switching profile!" xml:space="preserve">
|
||||||
<source>Error switching profile!</source>
|
<source>Error switching profile!</source>
|
||||||
<target>Грешка при смяна на профил!</target>
|
<target>Грешка при смяна на профил!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>alertTitle</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
||||||
<source>Error synchronizing connection</source>
|
<source>Error synchronizing connection</source>
|
||||||
@@ -2979,8 +3016,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>Грешка: %@</target>
|
<target>Грешка: %@</target>
|
||||||
<note>file error text
|
<note>alert message</note>
|
||||||
snd error text</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
||||||
<source>Error: URL is invalid</source>
|
<source>Error: URL is invalid</source>
|
||||||
@@ -3216,6 +3252,10 @@ This is your own one-time link!</source>
|
|||||||
<source>Forward messages without files?</source>
|
<source>Forward messages without files?</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Forward up to 20 messages at once." xml:space="preserve">
|
||||||
|
<source>Forward up to 20 messages at once.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Forwarded" xml:space="preserve">
|
<trans-unit id="Forwarded" xml:space="preserve">
|
||||||
<source>Forwarded</source>
|
<source>Forwarded</source>
|
||||||
<target>Препратено</target>
|
<target>Препратено</target>
|
||||||
@@ -3593,6 +3633,11 @@ Error: %2$@</source>
|
|||||||
<target>Импортиране на архив</target>
|
<target>Импортиране на архив</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Improved delivery, reduced traffic usage. More improvements are coming soon!" xml:space="preserve">
|
||||||
|
<source>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Improved message delivery" xml:space="preserve">
|
<trans-unit id="Improved message delivery" xml:space="preserve">
|
||||||
<source>Improved message delivery</source>
|
<source>Improved message delivery</source>
|
||||||
<target>Подобрена доставка на съобщения</target>
|
<target>Подобрена доставка на съобщения</target>
|
||||||
@@ -4358,6 +4403,14 @@ This is your link for group %@!</source>
|
|||||||
<target>Нов kод за достъп</target>
|
<target>Нов kод за достъп</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used every time you start the app." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used every time you start the app.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used for each server." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used for each server.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="New chat" xml:space="preserve">
|
<trans-unit id="New chat" xml:space="preserve">
|
||||||
<source>New chat</source>
|
<source>New chat</source>
|
||||||
<target>Нов чат</target>
|
<target>Нов чат</target>
|
||||||
@@ -4474,6 +4527,14 @@ This is your link for group %@!</source>
|
|||||||
<target>Няма мрежова връзка</target>
|
<target>Няма мрежова връзка</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record speech" xml:space="preserve">
|
||||||
|
<source>No permission to record speech</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record video" xml:space="preserve">
|
||||||
|
<source>No permission to record video</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
||||||
<source>No permission to record voice message</source>
|
<source>No permission to record voice message</source>
|
||||||
<target>Няма разрешение за запис на гласово съобщение</target>
|
<target>Няма разрешение за запис на гласово съобщение</target>
|
||||||
@@ -5877,6 +5938,10 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<source>Sent via proxy</source>
|
<source>Sent via proxy</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Server address" xml:space="preserve">
|
<trans-unit id="Server address" xml:space="preserve">
|
||||||
<source>Server address</source>
|
<source>Server address</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -6160,6 +6225,10 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>Еднократна покана за SimpleX</target>
|
<target>Еднократна покана за SimpleX</target>
|
||||||
<note>simplex link type</note>
|
<note>simplex link type</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SimpleX protocols reviewed by Trail of Bits." xml:space="preserve">
|
||||||
|
<source>SimpleX protocols reviewed by Trail of Bits.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
||||||
<source>Simplified incognito mode</source>
|
<source>Simplified incognito mode</source>
|
||||||
<target>Опростен режим инкогнито</target>
|
<target>Опростен режим инкогнито</target>
|
||||||
@@ -6324,6 +6393,14 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>Подкрепете SimpleX Chat</target>
|
<target>Подкрепете SimpleX Chat</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch audio and video during the call." xml:space="preserve">
|
||||||
|
<source>Switch audio and video during the call.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch chat profile for 1-time invitations." xml:space="preserve">
|
||||||
|
<source>Switch chat profile for 1-time invitations.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="System" xml:space="preserve">
|
<trans-unit id="System" xml:space="preserve">
|
||||||
<source>System</source>
|
<source>System</source>
|
||||||
<target>Системен</target>
|
<target>Системен</target>
|
||||||
@@ -6677,6 +6754,14 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||||||
Ще бъдете подканени да извършите идентификация, преди тази функция да бъде активирана.</target>
|
Ще бъдете подканени да извършите идентификация, преди тази функция да бъде активирана.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="To record speech please grant permission to use Microphone." xml:space="preserve">
|
||||||
|
<source>To record speech please grant permission to use Microphone.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="To record video please grant permission to use Camera." xml:space="preserve">
|
||||||
|
<source>To record video please grant permission to use Camera.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
||||||
<source>To record voice message please grant permission to use Microphone.</source>
|
<source>To record voice message please grant permission to use Microphone.</source>
|
||||||
<target>За да запишете гласово съобщение, моля, дайте разрешение за използване на микрофон.</target>
|
<target>За да запишете гласово съобщение, моля, дайте разрешение за използване на микрофон.</target>
|
||||||
@@ -7001,11 +7086,6 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
<source>Use the app with one hand.</source>
|
<source>Use the app with one hand.</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User profile" xml:space="preserve">
|
|
||||||
<source>User profile</source>
|
|
||||||
<target>Потребителски профил</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User selection" xml:space="preserve">
|
<trans-unit id="User selection" xml:space="preserve">
|
||||||
<source>User selection</source>
|
<source>User selection</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -7267,11 +7347,6 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
<source>XFTP server</source>
|
<source>XFTP server</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="You" xml:space="preserve">
|
|
||||||
<source>You</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">
|
<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>
|
<source>You **must not** use the same database on two devices.</source>
|
||||||
<target>**Не трябва** да използвате една и съща база данни на две устройства.</target>
|
<target>**Не трябва** да използвате една и съща база данни на две устройства.</target>
|
||||||
|
|||||||
@@ -715,7 +715,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All profiles" xml:space="preserve">
|
<trans-unit id="All profiles" xml:space="preserve">
|
||||||
<source>All profiles</source>
|
<source>All profiles</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>profile dropdown</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||||
<source>All your contacts will remain connected.</source>
|
<source>All your contacts will remain connected.</source>
|
||||||
@@ -898,6 +898,10 @@
|
|||||||
<target>Přístupový kód aplikace je nahrazen sebedestrukčním přístupovým heslem.</target>
|
<target>Přístupový kód aplikace je nahrazen sebedestrukčním přístupovým heslem.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="App session" xml:space="preserve">
|
||||||
|
<source>App session</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="App version" xml:space="preserve">
|
<trans-unit id="App version" xml:space="preserve">
|
||||||
<source>App version</source>
|
<source>App version</source>
|
||||||
<target>Verze aplikace</target>
|
<target>Verze aplikace</target>
|
||||||
@@ -1024,10 +1028,18 @@
|
|||||||
<target>Špatný hash zprávy</target>
|
<target>Špatný hash zprávy</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better calls" xml:space="preserve">
|
||||||
|
<source>Better calls</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better groups" xml:space="preserve">
|
<trans-unit id="Better groups" xml:space="preserve">
|
||||||
<source>Better groups</source>
|
<source>Better groups</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better message dates." xml:space="preserve">
|
||||||
|
<source>Better message dates.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better messages" xml:space="preserve">
|
<trans-unit id="Better messages" xml:space="preserve">
|
||||||
<source>Better messages</source>
|
<source>Better messages</source>
|
||||||
<target>Lepší zprávy</target>
|
<target>Lepší zprávy</target>
|
||||||
@@ -1037,6 +1049,18 @@
|
|||||||
<source>Better networking</source>
|
<source>Better networking</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better notifications" xml:space="preserve">
|
||||||
|
<source>Better notifications</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||||
|
<source>Better security ✅</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better user experience" xml:space="preserve">
|
||||||
|
<source>Better user experience</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Black" xml:space="preserve">
|
<trans-unit id="Black" xml:space="preserve">
|
||||||
<source>Black</source>
|
<source>Black</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -1298,6 +1322,11 @@
|
|||||||
<source>Chat preferences were changed.</source>
|
<source>Chat preferences were changed.</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat profile" xml:space="preserve">
|
||||||
|
<source>Chat profile</source>
|
||||||
|
<target>Profil uživatele</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Chat theme" xml:space="preserve">
|
<trans-unit id="Chat theme" xml:space="preserve">
|
||||||
<source>Chat theme</source>
|
<source>Chat theme</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -1774,6 +1803,10 @@ This is your own one-time link!</source>
|
|||||||
<target>Vlastní čas</target>
|
<target>Vlastní čas</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Customizable message shape." xml:space="preserve">
|
||||||
|
<source>Customizable message shape.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Customize theme" xml:space="preserve">
|
<trans-unit id="Customize theme" xml:space="preserve">
|
||||||
<source>Customize theme</source>
|
<source>Customize theme</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -2060,6 +2093,10 @@ This is your own one-time link!</source>
|
|||||||
<target>Smazat starou databázi?</target>
|
<target>Smazat starou databázi?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Delete or moderate up to 200 messages." xml:space="preserve">
|
||||||
|
<source>Delete or moderate up to 200 messages.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
||||||
<source>Delete pending connection?</source>
|
<source>Delete pending connection?</source>
|
||||||
<target>Smazat čekající připojení?</target>
|
<target>Smazat čekající připojení?</target>
|
||||||
@@ -2836,7 +2873,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error switching profile!" xml:space="preserve">
|
<trans-unit id="Error switching profile!" xml:space="preserve">
|
||||||
<source>Error switching profile!</source>
|
<source>Error switching profile!</source>
|
||||||
<target>Chyba při přepínání profilu!</target>
|
<target>Chyba při přepínání profilu!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>alertTitle</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
||||||
<source>Error synchronizing connection</source>
|
<source>Error synchronizing connection</source>
|
||||||
@@ -2879,8 +2916,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>Chyba: %@</target>
|
<target>Chyba: %@</target>
|
||||||
<note>file error text
|
<note>alert message</note>
|
||||||
snd error text</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
||||||
<source>Error: URL is invalid</source>
|
<source>Error: URL is invalid</source>
|
||||||
@@ -3108,6 +3144,10 @@ This is your own one-time link!</source>
|
|||||||
<source>Forward messages without files?</source>
|
<source>Forward messages without files?</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Forward up to 20 messages at once." xml:space="preserve">
|
||||||
|
<source>Forward up to 20 messages at once.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Forwarded" xml:space="preserve">
|
<trans-unit id="Forwarded" xml:space="preserve">
|
||||||
<source>Forwarded</source>
|
<source>Forwarded</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -3474,6 +3514,11 @@ Error: %2$@</source>
|
|||||||
<source>Importing archive</source>
|
<source>Importing archive</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Improved delivery, reduced traffic usage. More improvements are coming soon!" xml:space="preserve">
|
||||||
|
<source>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Improved message delivery" xml:space="preserve">
|
<trans-unit id="Improved message delivery" xml:space="preserve">
|
||||||
<source>Improved message delivery</source>
|
<source>Improved message delivery</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -4202,6 +4247,14 @@ This is your link for group %@!</source>
|
|||||||
<target>Nové heslo</target>
|
<target>Nové heslo</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used every time you start the app." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used every time you start the app.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used for each server." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used for each server.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="New chat" xml:space="preserve">
|
<trans-unit id="New chat" xml:space="preserve">
|
||||||
<source>New chat</source>
|
<source>New chat</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -4316,6 +4369,14 @@ This is your link for group %@!</source>
|
|||||||
<source>No network connection</source>
|
<source>No network connection</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record speech" xml:space="preserve">
|
||||||
|
<source>No permission to record speech</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record video" xml:space="preserve">
|
||||||
|
<source>No permission to record video</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
||||||
<source>No permission to record voice message</source>
|
<source>No permission to record voice message</source>
|
||||||
<target>Nemáte oprávnění nahrávat hlasové zprávy</target>
|
<target>Nemáte oprávnění nahrávat hlasové zprávy</target>
|
||||||
@@ -5679,6 +5740,10 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<source>Sent via proxy</source>
|
<source>Sent via proxy</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Server address" xml:space="preserve">
|
<trans-unit id="Server address" xml:space="preserve">
|
||||||
<source>Server address</source>
|
<source>Server address</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -5955,6 +6020,10 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>Jednorázová pozvánka SimpleX</target>
|
<target>Jednorázová pozvánka SimpleX</target>
|
||||||
<note>simplex link type</note>
|
<note>simplex link type</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SimpleX protocols reviewed by Trail of Bits." xml:space="preserve">
|
||||||
|
<source>SimpleX protocols reviewed by Trail of Bits.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
||||||
<source>Simplified incognito mode</source>
|
<source>Simplified incognito mode</source>
|
||||||
<target>Zjednodušený inkognito režim</target>
|
<target>Zjednodušený inkognito režim</target>
|
||||||
@@ -6115,6 +6184,14 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>Podpořte SimpleX Chat</target>
|
<target>Podpořte SimpleX Chat</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch audio and video during the call." xml:space="preserve">
|
||||||
|
<source>Switch audio and video during the call.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch chat profile for 1-time invitations." xml:space="preserve">
|
||||||
|
<source>Switch chat profile for 1-time invitations.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="System" xml:space="preserve">
|
<trans-unit id="System" xml:space="preserve">
|
||||||
<source>System</source>
|
<source>System</source>
|
||||||
<target>Systém</target>
|
<target>Systém</target>
|
||||||
@@ -6456,6 +6533,14 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||||||
Před zapnutím této funkce budete vyzváni k dokončení ověření.</target>
|
Před zapnutím této funkce budete vyzváni k dokončení ověření.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="To record speech please grant permission to use Microphone." xml:space="preserve">
|
||||||
|
<source>To record speech please grant permission to use Microphone.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="To record video please grant permission to use Camera." xml:space="preserve">
|
||||||
|
<source>To record video please grant permission to use Camera.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
||||||
<source>To record voice message please grant permission to use Microphone.</source>
|
<source>To record voice message please grant permission to use Microphone.</source>
|
||||||
<target>Chcete-li nahrávat hlasové zprávy, udělte povolení k použití mikrofonu.</target>
|
<target>Chcete-li nahrávat hlasové zprávy, udělte povolení k použití mikrofonu.</target>
|
||||||
@@ -6766,11 +6851,6 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
|
|||||||
<source>Use the app with one hand.</source>
|
<source>Use the app with one hand.</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User profile" xml:space="preserve">
|
|
||||||
<source>User profile</source>
|
|
||||||
<target>Profil uživatele</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User selection" xml:space="preserve">
|
<trans-unit id="User selection" xml:space="preserve">
|
||||||
<source>User selection</source>
|
<source>User selection</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -7015,11 +7095,6 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
|
|||||||
<source>XFTP server</source>
|
<source>XFTP server</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="You" xml:space="preserve">
|
|
||||||
<source>You</source>
|
|
||||||
<target>Vy</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">
|
<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>
|
<source>You **must not** use the same database on two devices.</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
|
|||||||
@@ -164,18 +164,22 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
|
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
|
||||||
<source>%d file(s) are still being downloaded.</source>
|
<source>%d file(s) are still being downloaded.</source>
|
||||||
|
<target>%d Datei(en) wird/werden immer noch heruntergeladen.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
|
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
|
||||||
<source>%d file(s) failed to download.</source>
|
<source>%d file(s) failed to download.</source>
|
||||||
|
<target>Bei %d Datei(en) ist das Herunterladen fehlgeschlagen.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
|
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
|
||||||
<source>%d file(s) were deleted.</source>
|
<source>%d file(s) were deleted.</source>
|
||||||
|
<target>%d Datei(en) wurde(n) gelöscht.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
|
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
|
||||||
<source>%d file(s) were not downloaded.</source>
|
<source>%d file(s) were not downloaded.</source>
|
||||||
|
<target>%d Datei(en) wurde(n) nicht heruntergeladen.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d hours" xml:space="preserve">
|
<trans-unit id="%d hours" xml:space="preserve">
|
||||||
@@ -185,6 +189,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d messages not forwarded" xml:space="preserve">
|
<trans-unit id="%d messages not forwarded" xml:space="preserve">
|
||||||
<source>%d messages not forwarded</source>
|
<source>%d messages not forwarded</source>
|
||||||
|
<target>%d Nachrichten wurden nicht weitergeleitet</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d min" xml:space="preserve">
|
<trans-unit id="%d min" xml:space="preserve">
|
||||||
@@ -748,7 +753,7 @@
|
|||||||
<trans-unit id="All profiles" xml:space="preserve">
|
<trans-unit id="All profiles" xml:space="preserve">
|
||||||
<source>All profiles</source>
|
<source>All profiles</source>
|
||||||
<target>Alle Profile</target>
|
<target>Alle Profile</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>profile dropdown</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||||
<source>All your contacts will remain connected.</source>
|
<source>All your contacts will remain connected.</source>
|
||||||
@@ -940,6 +945,11 @@
|
|||||||
<target>App-Zugangscode wurde durch den Selbstzerstörungs-Zugangscode ersetzt.</target>
|
<target>App-Zugangscode wurde durch den Selbstzerstörungs-Zugangscode ersetzt.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="App session" xml:space="preserve">
|
||||||
|
<source>App session</source>
|
||||||
|
<target>App-Sitzung</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="App version" xml:space="preserve">
|
<trans-unit id="App version" xml:space="preserve">
|
||||||
<source>App version</source>
|
<source>App version</source>
|
||||||
<target>App Version</target>
|
<target>App Version</target>
|
||||||
@@ -1075,11 +1085,21 @@
|
|||||||
<target>Ungültiger Nachrichten-Hash</target>
|
<target>Ungültiger Nachrichten-Hash</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better calls" xml:space="preserve">
|
||||||
|
<source>Better calls</source>
|
||||||
|
<target>Verbesserte Anrufe</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better groups" xml:space="preserve">
|
<trans-unit id="Better groups" xml:space="preserve">
|
||||||
<source>Better groups</source>
|
<source>Better groups</source>
|
||||||
<target>Bessere Gruppen</target>
|
<target>Bessere Gruppen</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better message dates." xml:space="preserve">
|
||||||
|
<source>Better message dates.</source>
|
||||||
|
<target>Verbesserte Nachrichten-Datumsinformation</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better messages" xml:space="preserve">
|
<trans-unit id="Better messages" xml:space="preserve">
|
||||||
<source>Better messages</source>
|
<source>Better messages</source>
|
||||||
<target>Verbesserungen bei Nachrichten</target>
|
<target>Verbesserungen bei Nachrichten</target>
|
||||||
@@ -1090,6 +1110,21 @@
|
|||||||
<target>Kontrollieren Sie Ihr Netzwerk</target>
|
<target>Kontrollieren Sie Ihr Netzwerk</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better notifications" xml:space="preserve">
|
||||||
|
<source>Better notifications</source>
|
||||||
|
<target>Verbesserte Benachrichtigungen</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||||
|
<source>Better security ✅</source>
|
||||||
|
<target>Verbesserte Sicherheit ✅</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better user experience" xml:space="preserve">
|
||||||
|
<source>Better user experience</source>
|
||||||
|
<target>Verbesserte Nutzer-Erfahrung</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Black" xml:space="preserve">
|
<trans-unit id="Black" xml:space="preserve">
|
||||||
<source>Black</source>
|
<source>Black</source>
|
||||||
<target>Schwarz</target>
|
<target>Schwarz</target>
|
||||||
@@ -1376,6 +1411,11 @@
|
|||||||
<target>Die Chat-Präferenzen wurden geändert.</target>
|
<target>Die Chat-Präferenzen wurden geändert.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat profile" xml:space="preserve">
|
||||||
|
<source>Chat profile</source>
|
||||||
|
<target>Benutzerprofil</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Chat theme" xml:space="preserve">
|
<trans-unit id="Chat theme" xml:space="preserve">
|
||||||
<source>Chat theme</source>
|
<source>Chat theme</source>
|
||||||
<target>Chat-Design</target>
|
<target>Chat-Design</target>
|
||||||
@@ -1777,7 +1817,7 @@ Das ist Ihr eigener Einmal-Link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Corner" xml:space="preserve">
|
<trans-unit id="Corner" xml:space="preserve">
|
||||||
<source>Corner</source>
|
<source>Corner</source>
|
||||||
<target>Ecke</target>
|
<target>Abrundung Ecken</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Correct name to %@?" xml:space="preserve">
|
<trans-unit id="Correct name to %@?" xml:space="preserve">
|
||||||
@@ -1905,6 +1945,11 @@ Das ist Ihr eigener Einmal-Link!</target>
|
|||||||
<target>Zeit anpassen</target>
|
<target>Zeit anpassen</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Customizable message shape." xml:space="preserve">
|
||||||
|
<source>Customizable message shape.</source>
|
||||||
|
<target>Anpassbares Format des Nachrichtenfelds</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Customize theme" xml:space="preserve">
|
<trans-unit id="Customize theme" xml:space="preserve">
|
||||||
<source>Customize theme</source>
|
<source>Customize theme</source>
|
||||||
<target>Design anpassen</target>
|
<target>Design anpassen</target>
|
||||||
@@ -2199,6 +2244,11 @@ Das ist Ihr eigener Einmal-Link!</target>
|
|||||||
<target>Alte Datenbank löschen?</target>
|
<target>Alte Datenbank löschen?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Delete or moderate up to 200 messages." xml:space="preserve">
|
||||||
|
<source>Delete or moderate up to 200 messages.</source>
|
||||||
|
<target>Bis zu 200 Nachrichten löschen oder moderieren</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
||||||
<source>Delete pending connection?</source>
|
<source>Delete pending connection?</source>
|
||||||
<target>Ausstehende Verbindung löschen?</target>
|
<target>Ausstehende Verbindung löschen?</target>
|
||||||
@@ -2451,6 +2501,7 @@ Das ist Ihr eigener Einmal-Link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
|
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
|
||||||
<source>Do not use credentials with proxy.</source>
|
<source>Do not use credentials with proxy.</source>
|
||||||
|
<target>Verwenden Sie keine Anmeldeinformationen mit einem Proxy.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Don't create address" xml:space="preserve">
|
<trans-unit id="Don't create address" xml:space="preserve">
|
||||||
@@ -2496,6 +2547,7 @@ Das ist Ihr eigener Einmal-Link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Download files" xml:space="preserve">
|
<trans-unit id="Download files" xml:space="preserve">
|
||||||
<source>Download files</source>
|
<source>Download files</source>
|
||||||
|
<target>Dateien herunterladen</target>
|
||||||
<note>alert action</note>
|
<note>alert action</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Downloaded" xml:space="preserve">
|
<trans-unit id="Downloaded" xml:space="preserve">
|
||||||
@@ -3026,7 +3078,7 @@ Das ist Ihr eigener Einmal-Link!</target>
|
|||||||
<trans-unit id="Error switching profile!" xml:space="preserve">
|
<trans-unit id="Error switching profile!" xml:space="preserve">
|
||||||
<source>Error switching profile!</source>
|
<source>Error switching profile!</source>
|
||||||
<target>Fehler beim Umschalten des Profils!</target>
|
<target>Fehler beim Umschalten des Profils!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>alertTitle</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
||||||
<source>Error synchronizing connection</source>
|
<source>Error synchronizing connection</source>
|
||||||
@@ -3071,8 +3123,7 @@ Das ist Ihr eigener Einmal-Link!</target>
|
|||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>Fehler: %@</target>
|
<target>Fehler: %@</target>
|
||||||
<note>file error text
|
<note>alert message</note>
|
||||||
snd error text</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
||||||
<source>Error: URL is invalid</source>
|
<source>Error: URL is invalid</source>
|
||||||
@@ -3162,6 +3213,8 @@ Das ist Ihr eigener Einmal-Link!</target>
|
|||||||
<trans-unit id="File errors: %@" xml:space="preserve">
|
<trans-unit id="File errors: %@" xml:space="preserve">
|
||||||
<source>File errors:
|
<source>File errors:
|
||||||
%@</source>
|
%@</source>
|
||||||
|
<target>Datei-Fehler:
|
||||||
|
%@</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||||
@@ -3301,6 +3354,7 @@ Das ist Ihr eigener Einmal-Link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
|
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
|
||||||
<source>Forward %d message(s)?</source>
|
<source>Forward %d message(s)?</source>
|
||||||
|
<target>%d Nachricht(en) weiterleiten?</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward and save messages" xml:space="preserve">
|
<trans-unit id="Forward and save messages" xml:space="preserve">
|
||||||
@@ -3310,12 +3364,19 @@ Das ist Ihr eigener Einmal-Link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward messages" xml:space="preserve">
|
<trans-unit id="Forward messages" xml:space="preserve">
|
||||||
<source>Forward messages</source>
|
<source>Forward messages</source>
|
||||||
|
<target>Nachrichten weiterleiten</target>
|
||||||
<note>alert action</note>
|
<note>alert action</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward messages without files?" xml:space="preserve">
|
<trans-unit id="Forward messages without files?" xml:space="preserve">
|
||||||
<source>Forward messages without files?</source>
|
<source>Forward messages without files?</source>
|
||||||
|
<target>Nachrichten ohne Dateien weiterleiten?</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Forward up to 20 messages at once." xml:space="preserve">
|
||||||
|
<source>Forward up to 20 messages at once.</source>
|
||||||
|
<target>Bis zu 20 Nachrichten auf einmal weiterleiten</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Forwarded" xml:space="preserve">
|
<trans-unit id="Forwarded" xml:space="preserve">
|
||||||
<source>Forwarded</source>
|
<source>Forwarded</source>
|
||||||
<target>Weitergeleitet</target>
|
<target>Weitergeleitet</target>
|
||||||
@@ -3328,6 +3389,7 @@ Das ist Ihr eigener Einmal-Link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
|
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
|
||||||
<source>Forwarding %lld messages</source>
|
<source>Forwarding %lld messages</source>
|
||||||
|
<target>%lld Nachricht(en) wird/werden weitergeleitet</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
|
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
|
||||||
@@ -3626,6 +3688,7 @@ Fehler: %2$@</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="IP address" xml:space="preserve">
|
<trans-unit id="IP address" xml:space="preserve">
|
||||||
<source>IP address</source>
|
<source>IP address</source>
|
||||||
|
<target>IP-Adresse</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
|
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
|
||||||
@@ -3703,6 +3766,13 @@ Fehler: %2$@</target>
|
|||||||
<target>Archiv wird importiert</target>
|
<target>Archiv wird importiert</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Improved delivery, reduced traffic usage. More improvements are coming soon!" xml:space="preserve">
|
||||||
|
<source>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</source>
|
||||||
|
<target>Verbesserte Nachrichten-Auslieferung und verringerter Datenverbrauch.
|
||||||
|
Weitere Verbesserungen sind bald verfügbar!</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Improved message delivery" xml:space="preserve">
|
<trans-unit id="Improved message delivery" xml:space="preserve">
|
||||||
<source>Improved message delivery</source>
|
<source>Improved message delivery</source>
|
||||||
<target>Verbesserte Zustellung von Nachrichten</target>
|
<target>Verbesserte Zustellung von Nachrichten</target>
|
||||||
@@ -4330,6 +4400,7 @@ Das ist Ihr Link für die Gruppe %@!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
|
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
|
||||||
<source>Messages were deleted after you selected them.</source>
|
<source>Messages were deleted after you selected them.</source>
|
||||||
|
<target>Die Nachrichten wurden gelöscht, nachdem Sie sie ausgewählt hatten.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</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">
|
<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">
|
||||||
@@ -4487,6 +4558,16 @@ Das ist Ihr Link für die Gruppe %@!</target>
|
|||||||
<target>Neuer Zugangscode</target>
|
<target>Neuer Zugangscode</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used every time you start the app." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used every time you start the app.</source>
|
||||||
|
<target>Jedes Mal wenn Sie die App starten, werden neue SOCKS-Anmeldeinformationen genutzt</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used for each server." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used for each server.</source>
|
||||||
|
<target>Für jeden Server werden neue SOCKS-Anmeldeinformationen genutzt</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="New chat" xml:space="preserve">
|
<trans-unit id="New chat" xml:space="preserve">
|
||||||
<source>New chat</source>
|
<source>New chat</source>
|
||||||
<target>Neuer Chat</target>
|
<target>Neuer Chat</target>
|
||||||
@@ -4607,6 +4688,16 @@ Das ist Ihr Link für die Gruppe %@!</target>
|
|||||||
<target>Keine Netzwerkverbindung</target>
|
<target>Keine Netzwerkverbindung</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record speech" xml:space="preserve">
|
||||||
|
<source>No permission to record speech</source>
|
||||||
|
<target>Keine Genehmigung für Sprach-Aufnahmen</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record video" xml:space="preserve">
|
||||||
|
<source>No permission to record video</source>
|
||||||
|
<target>Keine Genehmigung für Video-Aufnahmen</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
||||||
<source>No permission to record voice message</source>
|
<source>No permission to record voice message</source>
|
||||||
<target>Keine Berechtigung für das Aufnehmen von Sprachnachrichten</target>
|
<target>Keine Berechtigung für das Aufnehmen von Sprachnachrichten</target>
|
||||||
@@ -4629,6 +4720,7 @@ Das ist Ihr Link für die Gruppe %@!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Nothing to forward!" xml:space="preserve">
|
<trans-unit id="Nothing to forward!" xml:space="preserve">
|
||||||
<source>Nothing to forward!</source>
|
<source>Nothing to forward!</source>
|
||||||
|
<target>Es gibt nichts zum Weiterleiten!</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Notifications" xml:space="preserve">
|
<trans-unit id="Notifications" xml:space="preserve">
|
||||||
@@ -4857,6 +4949,8 @@ Dies erfordert die Aktivierung eines VPNs.</target>
|
|||||||
<trans-unit id="Other file errors: %@" xml:space="preserve">
|
<trans-unit id="Other file errors: %@" xml:space="preserve">
|
||||||
<source>Other file errors:
|
<source>Other file errors:
|
||||||
%@</source>
|
%@</source>
|
||||||
|
<target>Andere(r) Datei-Fehler:
|
||||||
|
%@</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="PING count" xml:space="preserve">
|
<trans-unit id="PING count" xml:space="preserve">
|
||||||
@@ -4896,6 +4990,7 @@ Dies erfordert die Aktivierung eines VPNs.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Password" xml:space="preserve">
|
<trans-unit id="Password" xml:space="preserve">
|
||||||
<source>Password</source>
|
<source>Password</source>
|
||||||
|
<target>Passwort</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Password to show" xml:space="preserve">
|
<trans-unit id="Password to show" xml:space="preserve">
|
||||||
@@ -5049,6 +5144,7 @@ Fehler: %@</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Port" xml:space="preserve">
|
<trans-unit id="Port" xml:space="preserve">
|
||||||
<source>Port</source>
|
<source>Port</source>
|
||||||
|
<target>Port</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
|
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
|
||||||
@@ -5240,6 +5336,7 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Proxy requires password" xml:space="preserve">
|
<trans-unit id="Proxy requires password" xml:space="preserve">
|
||||||
<source>Proxy requires password</source>
|
<source>Proxy requires password</source>
|
||||||
|
<target>Der Proxy benötigt ein Passwort</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Push notifications" xml:space="preserve">
|
<trans-unit id="Push notifications" xml:space="preserve">
|
||||||
@@ -5650,6 +5747,7 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="SOCKS proxy" xml:space="preserve">
|
<trans-unit id="SOCKS proxy" xml:space="preserve">
|
||||||
<source>SOCKS proxy</source>
|
<source>SOCKS proxy</source>
|
||||||
|
<target>SOCKS-Proxy</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Safely receive files" xml:space="preserve">
|
<trans-unit id="Safely receive files" xml:space="preserve">
|
||||||
@@ -5765,6 +5863,7 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Saving %lld messages" xml:space="preserve">
|
<trans-unit id="Saving %lld messages" xml:space="preserve">
|
||||||
<source>Saving %lld messages</source>
|
<source>Saving %lld messages</source>
|
||||||
|
<target>Es wird/werden %lld Nachricht(en) gesichert</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Scale" xml:space="preserve">
|
<trans-unit id="Scale" xml:space="preserve">
|
||||||
@@ -6067,6 +6166,11 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen.</target>
|
|||||||
<target>Über einen Proxy gesendet</target>
|
<target>Über einen Proxy gesendet</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<target>Server</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Server address" xml:space="preserve">
|
<trans-unit id="Server address" xml:space="preserve">
|
||||||
<source>Server address</source>
|
<source>Server address</source>
|
||||||
<target>Server-Adresse</target>
|
<target>Server-Adresse</target>
|
||||||
@@ -6367,6 +6471,11 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen.</target>
|
|||||||
<target>SimpleX-Einmal-Einladung</target>
|
<target>SimpleX-Einmal-Einladung</target>
|
||||||
<note>simplex link type</note>
|
<note>simplex link type</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SimpleX protocols reviewed by Trail of Bits." xml:space="preserve">
|
||||||
|
<source>SimpleX protocols reviewed by Trail of Bits.</source>
|
||||||
|
<target>Die SimpleX-Protokolle wurden von Trail of Bits überprüft.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
||||||
<source>Simplified incognito mode</source>
|
<source>Simplified incognito mode</source>
|
||||||
<target>Vereinfachter Inkognito-Modus</target>
|
<target>Vereinfachter Inkognito-Modus</target>
|
||||||
@@ -6542,6 +6651,16 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen.</target>
|
|||||||
<target>Unterstützung von SimpleX Chat</target>
|
<target>Unterstützung von SimpleX Chat</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch audio and video during the call." xml:space="preserve">
|
||||||
|
<source>Switch audio and video during the call.</source>
|
||||||
|
<target>Während des Anrufs zwischen Audio und Video wechseln</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch chat profile for 1-time invitations." xml:space="preserve">
|
||||||
|
<source>Switch chat profile for 1-time invitations.</source>
|
||||||
|
<target>Das Chat-Profil für Einmal-Einladungen wechseln</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="System" xml:space="preserve">
|
<trans-unit id="System" xml:space="preserve">
|
||||||
<source>System</source>
|
<source>System</source>
|
||||||
<target>System</target>
|
<target>System</target>
|
||||||
@@ -6579,7 +6698,7 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Tail" xml:space="preserve">
|
<trans-unit id="Tail" xml:space="preserve">
|
||||||
<source>Tail</source>
|
<source>Tail</source>
|
||||||
<target>Sprechblase</target>
|
<target>Sprechblasen-Format</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Take picture" xml:space="preserve">
|
<trans-unit id="Take picture" xml:space="preserve">
|
||||||
@@ -6906,6 +7025,16 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||||||
Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funktion aktiviert wird.</target>
|
Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funktion aktiviert wird.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="To record speech please grant permission to use Microphone." xml:space="preserve">
|
||||||
|
<source>To record speech please grant permission to use Microphone.</source>
|
||||||
|
<target>Bitte erteilen Sie für Sprach-Aufnahmen die Genehmigung das Mikrofon zu nutzen.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="To record video please grant permission to use Camera." xml:space="preserve">
|
||||||
|
<source>To record video please grant permission to use Camera.</source>
|
||||||
|
<target>Bitte erteilen Sie für Video-Aufnahmen die Genehmigung die Kamera zu nutzen.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
||||||
<source>To record voice message please grant permission to use Microphone.</source>
|
<source>To record voice message please grant permission to use Microphone.</source>
|
||||||
<target>Bitte erlauben Sie die Nutzung des Mikrofons, um Sprachnachrichten aufnehmen zu können.</target>
|
<target>Bitte erlauben Sie die Nutzung des Mikrofons, um Sprachnachrichten aufnehmen zu können.</target>
|
||||||
@@ -7175,6 +7304,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
|
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
|
||||||
<source>Use SOCKS proxy</source>
|
<source>Use SOCKS proxy</source>
|
||||||
|
<target>SOCKS-Proxy nutzen</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
|
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
|
||||||
@@ -7242,11 +7372,6 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
|
|||||||
<target>Die App mit einer Hand bedienen.</target>
|
<target>Die App mit einer Hand bedienen.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User profile" xml:space="preserve">
|
|
||||||
<source>User profile</source>
|
|
||||||
<target>Benutzerprofil</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User selection" xml:space="preserve">
|
<trans-unit id="User selection" xml:space="preserve">
|
||||||
<source>User selection</source>
|
<source>User selection</source>
|
||||||
<target>Benutzer-Auswahl</target>
|
<target>Benutzer-Auswahl</target>
|
||||||
@@ -7254,6 +7379,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Username" xml:space="preserve">
|
<trans-unit id="Username" xml:space="preserve">
|
||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
|
<target>Benutzername</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
|
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
|
||||||
@@ -7516,11 +7642,6 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
|
|||||||
<target>XFTP-Server</target>
|
<target>XFTP-Server</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="You" xml:space="preserve">
|
|
||||||
<source>You</source>
|
|
||||||
<target>Profil</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">
|
<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>
|
<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>
|
<target>Sie dürfen die selbe Datenbank **nicht** auf zwei Geräten nutzen.</target>
|
||||||
@@ -7902,6 +8023,7 @@ Verbindungsanfrage wiederholen?</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
|
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
|
||||||
<source>Your credentials may be sent unencrypted.</source>
|
<source>Your credentials may be sent unencrypted.</source>
|
||||||
|
<target>Ihre Anmeldeinformationen können unverschlüsselt versendet werden.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
|
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
|
||||||
@@ -8381,7 +8503,7 @@ Verbindungsanfrage wiederholen?</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="expired" xml:space="preserve">
|
<trans-unit id="expired" xml:space="preserve">
|
||||||
<source>expired</source>
|
<source>expired</source>
|
||||||
<target>abgelaufen</target>
|
<target>Abgelaufen</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="forwarded" xml:space="preserve">
|
<trans-unit id="forwarded" xml:space="preserve">
|
||||||
@@ -8613,7 +8735,7 @@ Verbindungsanfrage wiederholen?</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="other" xml:space="preserve">
|
<trans-unit id="other" xml:space="preserve">
|
||||||
<source>other</source>
|
<source>other</source>
|
||||||
<target>andere</target>
|
<target>Andere</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="other errors" xml:space="preserve">
|
<trans-unit id="other errors" xml:space="preserve">
|
||||||
|
|||||||
@@ -4200,7 +4200,7 @@ SimpleX servers cannot see your profile.</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="## In reply to" xml:space="preserve" approved="no">
|
<trans-unit id="## In reply to" xml:space="preserve" approved="no">
|
||||||
<source>## In reply to</source>
|
<source>## In reply to</source>
|
||||||
<target state="translated">## Ως απαντηση σε</target>
|
<target state="translated">## Ως απάντηση σε</target>
|
||||||
<note>copied message info</note>
|
<note>copied message info</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%@ (current)" xml:space="preserve" approved="no">
|
<trans-unit id="%@ (current)" xml:space="preserve" approved="no">
|
||||||
|
|||||||
@@ -753,7 +753,7 @@
|
|||||||
<trans-unit id="All profiles" xml:space="preserve">
|
<trans-unit id="All profiles" xml:space="preserve">
|
||||||
<source>All profiles</source>
|
<source>All profiles</source>
|
||||||
<target>All profiles</target>
|
<target>All profiles</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>profile dropdown</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||||
<source>All your contacts will remain connected.</source>
|
<source>All your contacts will remain connected.</source>
|
||||||
@@ -945,6 +945,11 @@
|
|||||||
<target>App passcode is replaced with self-destruct passcode.</target>
|
<target>App passcode is replaced with self-destruct passcode.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="App session" xml:space="preserve">
|
||||||
|
<source>App session</source>
|
||||||
|
<target>App session</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="App version" xml:space="preserve">
|
<trans-unit id="App version" xml:space="preserve">
|
||||||
<source>App version</source>
|
<source>App version</source>
|
||||||
<target>App version</target>
|
<target>App version</target>
|
||||||
@@ -1080,11 +1085,21 @@
|
|||||||
<target>Bad message hash</target>
|
<target>Bad message hash</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better calls" xml:space="preserve">
|
||||||
|
<source>Better calls</source>
|
||||||
|
<target>Better calls</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better groups" xml:space="preserve">
|
<trans-unit id="Better groups" xml:space="preserve">
|
||||||
<source>Better groups</source>
|
<source>Better groups</source>
|
||||||
<target>Better groups</target>
|
<target>Better groups</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better message dates." xml:space="preserve">
|
||||||
|
<source>Better message dates.</source>
|
||||||
|
<target>Better message dates.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better messages" xml:space="preserve">
|
<trans-unit id="Better messages" xml:space="preserve">
|
||||||
<source>Better messages</source>
|
<source>Better messages</source>
|
||||||
<target>Better messages</target>
|
<target>Better messages</target>
|
||||||
@@ -1095,6 +1110,21 @@
|
|||||||
<target>Better networking</target>
|
<target>Better networking</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better notifications" xml:space="preserve">
|
||||||
|
<source>Better notifications</source>
|
||||||
|
<target>Better notifications</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||||
|
<source>Better security ✅</source>
|
||||||
|
<target>Better security ✅</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better user experience" xml:space="preserve">
|
||||||
|
<source>Better user experience</source>
|
||||||
|
<target>Better user experience</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Black" xml:space="preserve">
|
<trans-unit id="Black" xml:space="preserve">
|
||||||
<source>Black</source>
|
<source>Black</source>
|
||||||
<target>Black</target>
|
<target>Black</target>
|
||||||
@@ -1381,6 +1411,11 @@
|
|||||||
<target>Chat preferences were changed.</target>
|
<target>Chat preferences were changed.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat profile" xml:space="preserve">
|
||||||
|
<source>Chat profile</source>
|
||||||
|
<target>Chat profile</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Chat theme" xml:space="preserve">
|
<trans-unit id="Chat theme" xml:space="preserve">
|
||||||
<source>Chat theme</source>
|
<source>Chat theme</source>
|
||||||
<target>Chat theme</target>
|
<target>Chat theme</target>
|
||||||
@@ -1910,6 +1945,11 @@ This is your own one-time link!</target>
|
|||||||
<target>Custom time</target>
|
<target>Custom time</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Customizable message shape." xml:space="preserve">
|
||||||
|
<source>Customizable message shape.</source>
|
||||||
|
<target>Customizable message shape.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Customize theme" xml:space="preserve">
|
<trans-unit id="Customize theme" xml:space="preserve">
|
||||||
<source>Customize theme</source>
|
<source>Customize theme</source>
|
||||||
<target>Customize theme</target>
|
<target>Customize theme</target>
|
||||||
@@ -2204,6 +2244,11 @@ This is your own one-time link!</target>
|
|||||||
<target>Delete old database?</target>
|
<target>Delete old database?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Delete or moderate up to 200 messages." xml:space="preserve">
|
||||||
|
<source>Delete or moderate up to 200 messages.</source>
|
||||||
|
<target>Delete or moderate up to 200 messages.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
||||||
<source>Delete pending connection?</source>
|
<source>Delete pending connection?</source>
|
||||||
<target>Delete pending connection?</target>
|
<target>Delete pending connection?</target>
|
||||||
@@ -3033,7 +3078,7 @@ This is your own one-time link!</target>
|
|||||||
<trans-unit id="Error switching profile!" xml:space="preserve">
|
<trans-unit id="Error switching profile!" xml:space="preserve">
|
||||||
<source>Error switching profile!</source>
|
<source>Error switching profile!</source>
|
||||||
<target>Error switching profile!</target>
|
<target>Error switching profile!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>alertTitle</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
||||||
<source>Error synchronizing connection</source>
|
<source>Error synchronizing connection</source>
|
||||||
@@ -3078,8 +3123,7 @@ This is your own one-time link!</target>
|
|||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>Error: %@</target>
|
<target>Error: %@</target>
|
||||||
<note>file error text
|
<note>alert message</note>
|
||||||
snd error text</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
||||||
<source>Error: URL is invalid</source>
|
<source>Error: URL is invalid</source>
|
||||||
@@ -3328,6 +3372,11 @@ This is your own one-time link!</target>
|
|||||||
<target>Forward messages without files?</target>
|
<target>Forward messages without files?</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Forward up to 20 messages at once." xml:space="preserve">
|
||||||
|
<source>Forward up to 20 messages at once.</source>
|
||||||
|
<target>Forward up to 20 messages at once.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Forwarded" xml:space="preserve">
|
<trans-unit id="Forwarded" xml:space="preserve">
|
||||||
<source>Forwarded</source>
|
<source>Forwarded</source>
|
||||||
<target>Forwarded</target>
|
<target>Forwarded</target>
|
||||||
@@ -3717,6 +3766,13 @@ Error: %2$@</target>
|
|||||||
<target>Importing archive</target>
|
<target>Importing archive</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Improved delivery, reduced traffic usage. More improvements are coming soon!" xml:space="preserve">
|
||||||
|
<source>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</source>
|
||||||
|
<target>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Improved message delivery" xml:space="preserve">
|
<trans-unit id="Improved message delivery" xml:space="preserve">
|
||||||
<source>Improved message delivery</source>
|
<source>Improved message delivery</source>
|
||||||
<target>Improved message delivery</target>
|
<target>Improved message delivery</target>
|
||||||
@@ -4502,6 +4558,16 @@ This is your link for group %@!</target>
|
|||||||
<target>New Passcode</target>
|
<target>New Passcode</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used every time you start the app." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used every time you start the app.</source>
|
||||||
|
<target>New SOCKS credentials will be used every time you start the app.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used for each server." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used for each server.</source>
|
||||||
|
<target>New SOCKS credentials will be used for each server.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="New chat" xml:space="preserve">
|
<trans-unit id="New chat" xml:space="preserve">
|
||||||
<source>New chat</source>
|
<source>New chat</source>
|
||||||
<target>New chat</target>
|
<target>New chat</target>
|
||||||
@@ -4622,6 +4688,16 @@ This is your link for group %@!</target>
|
|||||||
<target>No network connection</target>
|
<target>No network connection</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record speech" xml:space="preserve">
|
||||||
|
<source>No permission to record speech</source>
|
||||||
|
<target>No permission to record speech</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record video" xml:space="preserve">
|
||||||
|
<source>No permission to record video</source>
|
||||||
|
<target>No permission to record video</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
||||||
<source>No permission to record voice message</source>
|
<source>No permission to record voice message</source>
|
||||||
<target>No permission to record voice message</target>
|
<target>No permission to record voice message</target>
|
||||||
@@ -6090,6 +6166,11 @@ Enable in *Network & servers* settings.</target>
|
|||||||
<target>Sent via proxy</target>
|
<target>Sent via proxy</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<target>Server</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Server address" xml:space="preserve">
|
<trans-unit id="Server address" xml:space="preserve">
|
||||||
<source>Server address</source>
|
<source>Server address</source>
|
||||||
<target>Server address</target>
|
<target>Server address</target>
|
||||||
@@ -6390,6 +6471,11 @@ Enable in *Network & servers* settings.</target>
|
|||||||
<target>SimpleX one-time invitation</target>
|
<target>SimpleX one-time invitation</target>
|
||||||
<note>simplex link type</note>
|
<note>simplex link type</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SimpleX protocols reviewed by Trail of Bits." xml:space="preserve">
|
||||||
|
<source>SimpleX protocols reviewed by Trail of Bits.</source>
|
||||||
|
<target>SimpleX protocols reviewed by Trail of Bits.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
||||||
<source>Simplified incognito mode</source>
|
<source>Simplified incognito mode</source>
|
||||||
<target>Simplified incognito mode</target>
|
<target>Simplified incognito mode</target>
|
||||||
@@ -6565,6 +6651,16 @@ Enable in *Network & servers* settings.</target>
|
|||||||
<target>Support SimpleX Chat</target>
|
<target>Support SimpleX Chat</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch audio and video during the call." xml:space="preserve">
|
||||||
|
<source>Switch audio and video during the call.</source>
|
||||||
|
<target>Switch audio and video during the call.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch chat profile for 1-time invitations." xml:space="preserve">
|
||||||
|
<source>Switch chat profile for 1-time invitations.</source>
|
||||||
|
<target>Switch chat profile for 1-time invitations.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="System" xml:space="preserve">
|
<trans-unit id="System" xml:space="preserve">
|
||||||
<source>System</source>
|
<source>System</source>
|
||||||
<target>System</target>
|
<target>System</target>
|
||||||
@@ -6929,6 +7025,16 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||||||
You will be prompted to complete authentication before this feature is enabled.</target>
|
You will be prompted to complete authentication before this feature is enabled.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="To record speech please grant permission to use Microphone." xml:space="preserve">
|
||||||
|
<source>To record speech please grant permission to use Microphone.</source>
|
||||||
|
<target>To record speech please grant permission to use Microphone.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="To record video please grant permission to use Camera." xml:space="preserve">
|
||||||
|
<source>To record video please grant permission to use Camera.</source>
|
||||||
|
<target>To record video please grant permission to use Camera.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
||||||
<source>To record voice message please grant permission to use Microphone.</source>
|
<source>To record voice message please grant permission to use Microphone.</source>
|
||||||
<target>To record voice message please grant permission to use Microphone.</target>
|
<target>To record voice message please grant permission to use Microphone.</target>
|
||||||
@@ -7266,11 +7372,6 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
<target>Use the app with one hand.</target>
|
<target>Use the app with one hand.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User profile" xml:space="preserve">
|
|
||||||
<source>User profile</source>
|
|
||||||
<target>User profile</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User selection" xml:space="preserve">
|
<trans-unit id="User selection" xml:space="preserve">
|
||||||
<source>User selection</source>
|
<source>User selection</source>
|
||||||
<target>User selection</target>
|
<target>User selection</target>
|
||||||
@@ -7541,11 +7642,6 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
<target>XFTP server</target>
|
<target>XFTP server</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="You" xml:space="preserve">
|
|
||||||
<source>You</source>
|
|
||||||
<target>You</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">
|
<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>
|
<source>You **must not** use the same database on two devices.</source>
|
||||||
<target>You **must not** use the same database on two devices.</target>
|
<target>You **must not** use the same database on two devices.</target>
|
||||||
|
|||||||
@@ -139,6 +139,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%@, %@" xml:space="preserve">
|
<trans-unit id="%@, %@" xml:space="preserve">
|
||||||
<source>%1$@, %2$@</source>
|
<source>%1$@, %2$@</source>
|
||||||
|
<target>%1$@, %2$@</target>
|
||||||
<note>format for date separator in chat</note>
|
<note>format for date separator in chat</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%@, %@ and %lld members" xml:space="preserve">
|
<trans-unit id="%@, %@ and %lld members" xml:space="preserve">
|
||||||
@@ -163,18 +164,22 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
|
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
|
||||||
<source>%d file(s) are still being downloaded.</source>
|
<source>%d file(s) are still being downloaded.</source>
|
||||||
|
<target>%d archivo(s) se está(n) descargando todavía.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
|
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
|
||||||
<source>%d file(s) failed to download.</source>
|
<source>%d file(s) failed to download.</source>
|
||||||
|
<target>La descarga ha fallado para %d archivo(s).</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
|
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
|
||||||
<source>%d file(s) were deleted.</source>
|
<source>%d file(s) were deleted.</source>
|
||||||
|
<target>%d archivo(s) ha(n) sido eliminado(s).</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
|
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
|
||||||
<source>%d file(s) were not downloaded.</source>
|
<source>%d file(s) were not downloaded.</source>
|
||||||
|
<target>%d archivo(s) no se ha(n) descargado.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d hours" xml:space="preserve">
|
<trans-unit id="%d hours" xml:space="preserve">
|
||||||
@@ -184,6 +189,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d messages not forwarded" xml:space="preserve">
|
<trans-unit id="%d messages not forwarded" xml:space="preserve">
|
||||||
<source>%d messages not forwarded</source>
|
<source>%d messages not forwarded</source>
|
||||||
|
<target>%d mensajes no enviados</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d min" xml:space="preserve">
|
<trans-unit id="%d min" xml:space="preserve">
|
||||||
@@ -531,7 +537,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="A new random profile will be shared." xml:space="preserve">
|
<trans-unit id="A new random profile will be shared." xml:space="preserve">
|
||||||
<source>A new random profile will be shared.</source>
|
<source>A new random profile will be shared.</source>
|
||||||
<target>Se compartirá un perfil nuevo aleatorio.</target>
|
<target>Compartirás un perfil nuevo aleatorio.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="A separate TCP connection will be used **for each chat profile you have in the app**." xml:space="preserve">
|
<trans-unit id="A separate TCP connection will be used **for each chat profile you have in the app**." xml:space="preserve">
|
||||||
@@ -747,7 +753,7 @@
|
|||||||
<trans-unit id="All profiles" xml:space="preserve">
|
<trans-unit id="All profiles" xml:space="preserve">
|
||||||
<source>All profiles</source>
|
<source>All profiles</source>
|
||||||
<target>Todos los perfiles</target>
|
<target>Todos los perfiles</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>profile dropdown</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||||
<source>All your contacts will remain connected.</source>
|
<source>All your contacts will remain connected.</source>
|
||||||
@@ -939,6 +945,11 @@
|
|||||||
<target>El código de acceso será reemplazado por código de autodestrucción.</target>
|
<target>El código de acceso será reemplazado por código de autodestrucción.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="App session" xml:space="preserve">
|
||||||
|
<source>App session</source>
|
||||||
|
<target>Sesión de aplicación</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="App version" xml:space="preserve">
|
<trans-unit id="App version" xml:space="preserve">
|
||||||
<source>App version</source>
|
<source>App version</source>
|
||||||
<target>Versión de la aplicación</target>
|
<target>Versión de la aplicación</target>
|
||||||
@@ -1046,6 +1057,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Auto-accept settings" xml:space="preserve">
|
<trans-unit id="Auto-accept settings" xml:space="preserve">
|
||||||
<source>Auto-accept settings</source>
|
<source>Auto-accept settings</source>
|
||||||
|
<target>Auto aceptar configuración</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Back" xml:space="preserve">
|
<trans-unit id="Back" xml:space="preserve">
|
||||||
@@ -1073,11 +1085,21 @@
|
|||||||
<target>Hash de mensaje incorrecto</target>
|
<target>Hash de mensaje incorrecto</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better calls" xml:space="preserve">
|
||||||
|
<source>Better calls</source>
|
||||||
|
<target>Llamadas mejoradas</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better groups" xml:space="preserve">
|
<trans-unit id="Better groups" xml:space="preserve">
|
||||||
<source>Better groups</source>
|
<source>Better groups</source>
|
||||||
<target>Grupos mejorados</target>
|
<target>Grupos mejorados</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better message dates." xml:space="preserve">
|
||||||
|
<source>Better message dates.</source>
|
||||||
|
<target>Sistema de fechas mejorado.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better messages" xml:space="preserve">
|
<trans-unit id="Better messages" xml:space="preserve">
|
||||||
<source>Better messages</source>
|
<source>Better messages</source>
|
||||||
<target>Mensajes mejorados</target>
|
<target>Mensajes mejorados</target>
|
||||||
@@ -1088,6 +1110,21 @@
|
|||||||
<target>Uso de red mejorado</target>
|
<target>Uso de red mejorado</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better notifications" xml:space="preserve">
|
||||||
|
<source>Better notifications</source>
|
||||||
|
<target>Notificaciones mejoradas</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||||
|
<source>Better security ✅</source>
|
||||||
|
<target>Seguridad mejorada ✅</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better user experience" xml:space="preserve">
|
||||||
|
<source>Better user experience</source>
|
||||||
|
<target>Experiencia de usuario mejorada</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Black" xml:space="preserve">
|
<trans-unit id="Black" xml:space="preserve">
|
||||||
<source>Black</source>
|
<source>Black</source>
|
||||||
<target>Negro</target>
|
<target>Negro</target>
|
||||||
@@ -1371,8 +1408,14 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Chat preferences were changed." xml:space="preserve">
|
<trans-unit id="Chat preferences were changed." xml:space="preserve">
|
||||||
<source>Chat preferences were changed.</source>
|
<source>Chat preferences were changed.</source>
|
||||||
|
<target>Las preferencias del chat han sido modificadas.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat profile" xml:space="preserve">
|
||||||
|
<source>Chat profile</source>
|
||||||
|
<target>Perfil de usuario</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Chat theme" xml:space="preserve">
|
<trans-unit id="Chat theme" xml:space="preserve">
|
||||||
<source>Chat theme</source>
|
<source>Chat theme</source>
|
||||||
<target>Tema de chat</target>
|
<target>Tema de chat</target>
|
||||||
@@ -1525,7 +1568,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Confirm that you remember database passphrase to migrate it." xml:space="preserve">
|
<trans-unit id="Confirm that you remember database passphrase to migrate it." xml:space="preserve">
|
||||||
<source>Confirm that you remember database passphrase to migrate it.</source>
|
<source>Confirm that you remember database passphrase to migrate it.</source>
|
||||||
<target>Para migrar confirma que recuerdas la frase de contraseña de la base de datos.</target>
|
<target>Para migrar la base de datos confirma que recuerdas la frase de contraseña.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Confirm upload" xml:space="preserve">
|
<trans-unit id="Confirm upload" xml:space="preserve">
|
||||||
@@ -1774,6 +1817,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Corner" xml:space="preserve">
|
<trans-unit id="Corner" xml:space="preserve">
|
||||||
<source>Corner</source>
|
<source>Corner</source>
|
||||||
|
<target>Esquina</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Correct name to %@?" xml:space="preserve">
|
<trans-unit id="Correct name to %@?" xml:space="preserve">
|
||||||
@@ -1901,6 +1945,11 @@ This is your own one-time link!</source>
|
|||||||
<target>Tiempo personalizado</target>
|
<target>Tiempo personalizado</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Customizable message shape." xml:space="preserve">
|
||||||
|
<source>Customizable message shape.</source>
|
||||||
|
<target>Forma personalizable de los mensajes.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Customize theme" xml:space="preserve">
|
<trans-unit id="Customize theme" xml:space="preserve">
|
||||||
<source>Customize theme</source>
|
<source>Customize theme</source>
|
||||||
<target>Personalizar tema</target>
|
<target>Personalizar tema</target>
|
||||||
@@ -1982,7 +2031,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</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">
|
||||||
<source>Database passphrase is different from saved in the keychain.</source>
|
<source>Database passphrase is different from saved in the keychain.</source>
|
||||||
<target>La contraseña es distinta a la almacenada en Keychain.</target>
|
<target>La contraseña es diferente a la almacenada en Keychain.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Database passphrase is required to open chat." xml:space="preserve">
|
<trans-unit id="Database passphrase is required to open chat." xml:space="preserve">
|
||||||
@@ -2195,6 +2244,11 @@ This is your own one-time link!</source>
|
|||||||
<target>¿Eliminar base de datos antigua?</target>
|
<target>¿Eliminar base de datos antigua?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Delete or moderate up to 200 messages." xml:space="preserve">
|
||||||
|
<source>Delete or moderate up to 200 messages.</source>
|
||||||
|
<target>Borra o modera hasta 200 mensajes a la vez.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
||||||
<source>Delete pending connection?</source>
|
<source>Delete pending connection?</source>
|
||||||
<target>¿Eliminar conexión pendiente?</target>
|
<target>¿Eliminar conexión pendiente?</target>
|
||||||
@@ -2407,7 +2461,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Disconnect desktop?" xml:space="preserve">
|
<trans-unit id="Disconnect desktop?" xml:space="preserve">
|
||||||
<source>Disconnect desktop?</source>
|
<source>Disconnect desktop?</source>
|
||||||
<target>¿Desconectar ordenador?</target>
|
<target>¿Desconectar del ordenador?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Discover and join groups" xml:space="preserve">
|
<trans-unit id="Discover and join groups" xml:space="preserve">
|
||||||
@@ -2447,6 +2501,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
|
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
|
||||||
<source>Do not use credentials with proxy.</source>
|
<source>Do not use credentials with proxy.</source>
|
||||||
|
<target>No uses credenciales con proxy.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Don't create address" xml:space="preserve">
|
<trans-unit id="Don't create address" xml:space="preserve">
|
||||||
@@ -2461,7 +2516,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Don't show again" xml:space="preserve">
|
<trans-unit id="Don't show again" xml:space="preserve">
|
||||||
<source>Don't show again</source>
|
<source>Don't show again</source>
|
||||||
<target>No mostrar de nuevo</target>
|
<target>No volver a mostrar</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Downgrade and open chat" xml:space="preserve">
|
<trans-unit id="Downgrade and open chat" xml:space="preserve">
|
||||||
@@ -2492,6 +2547,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Download files" xml:space="preserve">
|
<trans-unit id="Download files" xml:space="preserve">
|
||||||
<source>Download files</source>
|
<source>Download files</source>
|
||||||
|
<target>Descargar archivos</target>
|
||||||
<note>alert action</note>
|
<note>alert action</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Downloaded" xml:space="preserve">
|
<trans-unit id="Downloaded" xml:space="preserve">
|
||||||
@@ -2771,6 +2827,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error changing connection profile" xml:space="preserve">
|
<trans-unit id="Error changing connection profile" xml:space="preserve">
|
||||||
<source>Error changing connection profile</source>
|
<source>Error changing connection profile</source>
|
||||||
|
<target>Error al cambiar el perfil de conexión</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error changing role" xml:space="preserve">
|
<trans-unit id="Error changing role" xml:space="preserve">
|
||||||
@@ -2785,6 +2842,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error changing to incognito!" xml:space="preserve">
|
<trans-unit id="Error changing to incognito!" xml:space="preserve">
|
||||||
<source>Error changing to incognito!</source>
|
<source>Error changing to incognito!</source>
|
||||||
|
<target>¡Error al cambiar a incógnito!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
||||||
@@ -2909,6 +2967,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error migrating settings" xml:space="preserve">
|
<trans-unit id="Error migrating settings" xml:space="preserve">
|
||||||
<source>Error migrating settings</source>
|
<source>Error migrating settings</source>
|
||||||
|
<target>Error al migrar la configuración</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error opening chat" xml:space="preserve">
|
<trans-unit id="Error opening chat" xml:space="preserve">
|
||||||
@@ -3013,12 +3072,13 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error switching profile" xml:space="preserve">
|
<trans-unit id="Error switching profile" xml:space="preserve">
|
||||||
<source>Error switching profile</source>
|
<source>Error switching profile</source>
|
||||||
|
<target>Error al cambiar perfil</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error switching profile!" xml:space="preserve">
|
<trans-unit id="Error switching profile!" xml:space="preserve">
|
||||||
<source>Error switching profile!</source>
|
<source>Error switching profile!</source>
|
||||||
<target>¡Error al cambiar perfil!</target>
|
<target>¡Error al cambiar perfil!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>alertTitle</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
||||||
<source>Error synchronizing connection</source>
|
<source>Error synchronizing connection</source>
|
||||||
@@ -3063,8 +3123,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>Error: %@</target>
|
<target>Error: %@</target>
|
||||||
<note>file error text
|
<note>alert message</note>
|
||||||
snd error text</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
||||||
<source>Error: URL is invalid</source>
|
<source>Error: URL is invalid</source>
|
||||||
@@ -3154,6 +3213,8 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="File errors: %@" xml:space="preserve">
|
<trans-unit id="File errors: %@" xml:space="preserve">
|
||||||
<source>File errors:
|
<source>File errors:
|
||||||
%@</source>
|
%@</source>
|
||||||
|
<target>Error(es) de archivo
|
||||||
|
%@</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||||
@@ -3293,6 +3354,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
|
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
|
||||||
<source>Forward %d message(s)?</source>
|
<source>Forward %d message(s)?</source>
|
||||||
|
<target>¿Reenviar %d mensaje(s)?</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward and save messages" xml:space="preserve">
|
<trans-unit id="Forward and save messages" xml:space="preserve">
|
||||||
@@ -3302,12 +3364,19 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward messages" xml:space="preserve">
|
<trans-unit id="Forward messages" xml:space="preserve">
|
||||||
<source>Forward messages</source>
|
<source>Forward messages</source>
|
||||||
|
<target>Reenviar mensajes</target>
|
||||||
<note>alert action</note>
|
<note>alert action</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward messages without files?" xml:space="preserve">
|
<trans-unit id="Forward messages without files?" xml:space="preserve">
|
||||||
<source>Forward messages without files?</source>
|
<source>Forward messages without files?</source>
|
||||||
|
<target>¿Reenviar mensajes sin los archivos?</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Forward up to 20 messages at once." xml:space="preserve">
|
||||||
|
<source>Forward up to 20 messages at once.</source>
|
||||||
|
<target>Desplazamiento de hasta 20 mensajes.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Forwarded" xml:space="preserve">
|
<trans-unit id="Forwarded" xml:space="preserve">
|
||||||
<source>Forwarded</source>
|
<source>Forwarded</source>
|
||||||
<target>Reenviado</target>
|
<target>Reenviado</target>
|
||||||
@@ -3320,6 +3389,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
|
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
|
||||||
<source>Forwarding %lld messages</source>
|
<source>Forwarding %lld messages</source>
|
||||||
|
<target>Reenviando %lld mensajes</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
|
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
|
||||||
@@ -3373,12 +3443,12 @@ Error: %2$@</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Fully decentralized – visible only to members." xml:space="preserve">
|
<trans-unit id="Fully decentralized – visible only to members." xml:space="preserve">
|
||||||
<source>Fully decentralized – visible only to members.</source>
|
<source>Fully decentralized – visible only to members.</source>
|
||||||
<target>Completamente descentralizado y sólo visible para los miembros.</target>
|
<target>Totalmente descentralizado. Visible sólo para los miembros.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Fully re-implemented - work in background!" xml:space="preserve">
|
<trans-unit id="Fully re-implemented - work in background!" xml:space="preserve">
|
||||||
<source>Fully re-implemented - work in background!</source>
|
<source>Fully re-implemented - work in background!</source>
|
||||||
<target>Completamente reimplementado: ¡funciona en segundo plano!</target>
|
<target>Totalmente revisado. ¡Funciona en segundo plano!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Further reduced battery usage" xml:space="preserve">
|
<trans-unit id="Further reduced battery usage" xml:space="preserve">
|
||||||
@@ -3618,6 +3688,7 @@ Error: %2$@</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="IP address" xml:space="preserve">
|
<trans-unit id="IP address" xml:space="preserve">
|
||||||
<source>IP address</source>
|
<source>IP address</source>
|
||||||
|
<target>Dirección IP</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
|
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
|
||||||
@@ -3695,6 +3766,13 @@ Error: %2$@</target>
|
|||||||
<target>Importando archivo</target>
|
<target>Importando archivo</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Improved delivery, reduced traffic usage. More improvements are coming soon!" xml:space="preserve">
|
||||||
|
<source>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</source>
|
||||||
|
<target>Reducción del tráfico y entrega mejorada.
|
||||||
|
¡Pronto habrá nuevas mejoras!</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Improved message delivery" xml:space="preserve">
|
<trans-unit id="Improved message delivery" xml:space="preserve">
|
||||||
<source>Improved message delivery</source>
|
<source>Improved message delivery</source>
|
||||||
<target>Entrega de mensajes mejorada</target>
|
<target>Entrega de mensajes mejorada</target>
|
||||||
@@ -4097,7 +4175,7 @@ This is your link for group %@!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Local profile data only" xml:space="preserve">
|
<trans-unit id="Local profile data only" xml:space="preserve">
|
||||||
<source>Local profile data only</source>
|
<source>Local profile data only</source>
|
||||||
<target>Sólo datos del perfil local</target>
|
<target>Eliminar sólo el perfil</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Lock after" xml:space="preserve">
|
<trans-unit id="Lock after" xml:space="preserve">
|
||||||
@@ -4267,6 +4345,7 @@ This is your link for group %@!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Message shape" xml:space="preserve">
|
<trans-unit id="Message shape" xml:space="preserve">
|
||||||
<source>Message shape</source>
|
<source>Message shape</source>
|
||||||
|
<target>Forma del mensaje</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Message source remains private." xml:space="preserve">
|
<trans-unit id="Message source remains private." xml:space="preserve">
|
||||||
@@ -4321,6 +4400,7 @@ This is your link for group %@!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
|
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
|
||||||
<source>Messages were deleted after you selected them.</source>
|
<source>Messages were deleted after you selected them.</source>
|
||||||
|
<target>Los mensajes han sido borrados después de seleccionarlos.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</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">
|
<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">
|
||||||
@@ -4478,6 +4558,16 @@ This is your link for group %@!</source>
|
|||||||
<target>Código Nuevo</target>
|
<target>Código Nuevo</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used every time you start the app." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used every time you start the app.</source>
|
||||||
|
<target>Se usarán credenciales SOCKS nuevas cada vez que inicies la aplicación.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used for each server." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used for each server.</source>
|
||||||
|
<target>Se usarán credenciales SOCKS nuevas por cada servidor.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="New chat" xml:space="preserve">
|
<trans-unit id="New chat" xml:space="preserve">
|
||||||
<source>New chat</source>
|
<source>New chat</source>
|
||||||
<target>Nuevo chat</target>
|
<target>Nuevo chat</target>
|
||||||
@@ -4598,6 +4688,16 @@ This is your link for group %@!</source>
|
|||||||
<target>Sin conexión de red</target>
|
<target>Sin conexión de red</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record speech" xml:space="preserve">
|
||||||
|
<source>No permission to record speech</source>
|
||||||
|
<target>Sin permiso para grabación de voz</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record video" xml:space="preserve">
|
||||||
|
<source>No permission to record video</source>
|
||||||
|
<target>Sin permiso para grabación de vídeo</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
||||||
<source>No permission to record voice message</source>
|
<source>No permission to record voice message</source>
|
||||||
<target>Sin permiso para grabar mensajes de voz</target>
|
<target>Sin permiso para grabar mensajes de voz</target>
|
||||||
@@ -4620,6 +4720,7 @@ This is your link for group %@!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Nothing to forward!" xml:space="preserve">
|
<trans-unit id="Nothing to forward!" xml:space="preserve">
|
||||||
<source>Nothing to forward!</source>
|
<source>Nothing to forward!</source>
|
||||||
|
<target>¡Nada para reenviar!</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Notifications" xml:space="preserve">
|
<trans-unit id="Notifications" xml:space="preserve">
|
||||||
@@ -4848,6 +4949,8 @@ Requiere activación de la VPN.</target>
|
|||||||
<trans-unit id="Other file errors: %@" xml:space="preserve">
|
<trans-unit id="Other file errors: %@" xml:space="preserve">
|
||||||
<source>Other file errors:
|
<source>Other file errors:
|
||||||
%@</source>
|
%@</source>
|
||||||
|
<target>Otro(s) error(es) de archivo.
|
||||||
|
%@</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="PING count" xml:space="preserve">
|
<trans-unit id="PING count" xml:space="preserve">
|
||||||
@@ -4887,6 +4990,7 @@ Requiere activación de la VPN.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Password" xml:space="preserve">
|
<trans-unit id="Password" xml:space="preserve">
|
||||||
<source>Password</source>
|
<source>Password</source>
|
||||||
|
<target>Contraseña</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Password to show" xml:space="preserve">
|
<trans-unit id="Password to show" xml:space="preserve">
|
||||||
@@ -5040,11 +5144,12 @@ Error: %@</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Port" xml:space="preserve">
|
<trans-unit id="Port" xml:space="preserve">
|
||||||
<source>Port</source>
|
<source>Port</source>
|
||||||
|
<target>Puerto</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
|
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
|
||||||
<source>Possibly, certificate fingerprint in server address is incorrect</source>
|
<source>Possibly, certificate fingerprint in server address is incorrect</source>
|
||||||
<target>Posiblemente la huella digital del certificado en la dirección del servidor es incorrecta</target>
|
<target>Posiblemente la huella del certificado en la dirección del servidor es incorrecta</target>
|
||||||
<note>server test error</note>
|
<note>server test error</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Preserve the last message draft, with attachments." xml:space="preserve">
|
<trans-unit id="Preserve the last message draft, with attachments." xml:space="preserve">
|
||||||
@@ -5114,7 +5219,7 @@ Error: %@</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Profile and server connections" xml:space="preserve">
|
<trans-unit id="Profile and server connections" xml:space="preserve">
|
||||||
<source>Profile and server connections</source>
|
<source>Profile and server connections</source>
|
||||||
<target>Datos del perfil y conexiones</target>
|
<target>Eliminar perfil y conexiones</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Profile image" xml:space="preserve">
|
<trans-unit id="Profile image" xml:space="preserve">
|
||||||
@@ -5231,6 +5336,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Proxy requires password" xml:space="preserve">
|
<trans-unit id="Proxy requires password" xml:space="preserve">
|
||||||
<source>Proxy requires password</source>
|
<source>Proxy requires password</source>
|
||||||
|
<target>El proxy requiere contraseña</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Push notifications" xml:space="preserve">
|
<trans-unit id="Push notifications" xml:space="preserve">
|
||||||
@@ -5456,6 +5562,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Remove archive?" xml:space="preserve">
|
<trans-unit id="Remove archive?" xml:space="preserve">
|
||||||
<source>Remove archive?</source>
|
<source>Remove archive?</source>
|
||||||
|
<target>¿Eliminar archivo?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Remove image" xml:space="preserve">
|
<trans-unit id="Remove image" xml:space="preserve">
|
||||||
@@ -5640,6 +5747,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="SOCKS proxy" xml:space="preserve">
|
<trans-unit id="SOCKS proxy" xml:space="preserve">
|
||||||
<source>SOCKS proxy</source>
|
<source>SOCKS proxy</source>
|
||||||
|
<target>Proxy SOCKS</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Safely receive files" xml:space="preserve">
|
<trans-unit id="Safely receive files" xml:space="preserve">
|
||||||
@@ -5730,6 +5838,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Save your profile?" xml:space="preserve">
|
<trans-unit id="Save your profile?" xml:space="preserve">
|
||||||
<source>Save your profile?</source>
|
<source>Save your profile?</source>
|
||||||
|
<target>¿Guardar tu perfil?</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Saved" xml:space="preserve">
|
<trans-unit id="Saved" xml:space="preserve">
|
||||||
@@ -5754,6 +5863,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Saving %lld messages" xml:space="preserve">
|
<trans-unit id="Saving %lld messages" xml:space="preserve">
|
||||||
<source>Saving %lld messages</source>
|
<source>Saving %lld messages</source>
|
||||||
|
<target>Guardando %lld mensajes</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Scale" xml:space="preserve">
|
<trans-unit id="Scale" xml:space="preserve">
|
||||||
@@ -5838,6 +5948,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Select chat profile" xml:space="preserve">
|
<trans-unit id="Select chat profile" xml:space="preserve">
|
||||||
<source>Select chat profile</source>
|
<source>Select chat profile</source>
|
||||||
|
<target>Selecciona perfil de chat</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Selected %lld" xml:space="preserve">
|
<trans-unit id="Selected %lld" xml:space="preserve">
|
||||||
@@ -5887,7 +5998,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Send direct message to connect" xml:space="preserve">
|
<trans-unit id="Send direct message to connect" xml:space="preserve">
|
||||||
<source>Send direct message to connect</source>
|
<source>Send direct message to connect</source>
|
||||||
<target>Envia un mensaje para conectar</target>
|
<target>Envía un mensaje para conectar</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Send disappearing message" xml:space="preserve">
|
<trans-unit id="Send disappearing message" xml:space="preserve">
|
||||||
@@ -6055,6 +6166,11 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
<target>Mediante proxy</target>
|
<target>Mediante proxy</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<target>Servidor</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Server address" xml:space="preserve">
|
<trans-unit id="Server address" xml:space="preserve">
|
||||||
<source>Server address</source>
|
<source>Server address</source>
|
||||||
<target>Dirección del servidor</target>
|
<target>Dirección del servidor</target>
|
||||||
@@ -6082,7 +6198,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Server test failed!" xml:space="preserve">
|
<trans-unit id="Server test failed!" xml:space="preserve">
|
||||||
<source>Server test failed!</source>
|
<source>Server test failed!</source>
|
||||||
<target>¡Error en prueba del servidor!</target>
|
<target>¡Prueba no superada!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Server type" xml:space="preserve">
|
<trans-unit id="Server type" xml:space="preserve">
|
||||||
@@ -6177,6 +6293,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Settings were changed." xml:space="preserve">
|
<trans-unit id="Settings were changed." xml:space="preserve">
|
||||||
<source>Settings were changed.</source>
|
<source>Settings were changed.</source>
|
||||||
|
<target>La configuración ha sido modificada.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Shape profile images" xml:space="preserve">
|
<trans-unit id="Shape profile images" xml:space="preserve">
|
||||||
@@ -6216,6 +6333,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Share profile" xml:space="preserve">
|
<trans-unit id="Share profile" xml:space="preserve">
|
||||||
<source>Share profile</source>
|
<source>Share profile</source>
|
||||||
|
<target>Comparte perfil</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Share this 1-time invite link" xml:space="preserve">
|
<trans-unit id="Share this 1-time invite link" xml:space="preserve">
|
||||||
@@ -6353,6 +6471,11 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
<target>Invitación SimpleX de un uso</target>
|
<target>Invitación SimpleX de un uso</target>
|
||||||
<note>simplex link type</note>
|
<note>simplex link type</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SimpleX protocols reviewed by Trail of Bits." xml:space="preserve">
|
||||||
|
<source>SimpleX protocols reviewed by Trail of Bits.</source>
|
||||||
|
<target>Protocolos de SimpleX auditados por Trail of Bits.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
||||||
<source>Simplified incognito mode</source>
|
<source>Simplified incognito mode</source>
|
||||||
<target>Modo incógnito simplificado</target>
|
<target>Modo incógnito simplificado</target>
|
||||||
@@ -6385,6 +6508,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
|
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
|
||||||
<source>Some app settings were not migrated.</source>
|
<source>Some app settings were not migrated.</source>
|
||||||
|
<target>Algunas configuraciones de la app no han sido migradas.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
|
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
|
||||||
@@ -6527,6 +6651,16 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
<target>Soporte SimpleX Chat</target>
|
<target>Soporte SimpleX Chat</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch audio and video during the call." xml:space="preserve">
|
||||||
|
<source>Switch audio and video during the call.</source>
|
||||||
|
<target>Intercambia audio y video durante la llamada.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch chat profile for 1-time invitations." xml:space="preserve">
|
||||||
|
<source>Switch chat profile for 1-time invitations.</source>
|
||||||
|
<target>Cambia el perfil de chat para invitaciones de un solo uso.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="System" xml:space="preserve">
|
<trans-unit id="System" xml:space="preserve">
|
||||||
<source>System</source>
|
<source>System</source>
|
||||||
<target>Sistema</target>
|
<target>Sistema</target>
|
||||||
@@ -6564,6 +6698,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Tail" xml:space="preserve">
|
<trans-unit id="Tail" xml:space="preserve">
|
||||||
<source>Tail</source>
|
<source>Tail</source>
|
||||||
|
<target>Cola</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Take picture" xml:space="preserve">
|
<trans-unit id="Take picture" xml:space="preserve">
|
||||||
@@ -6613,7 +6748,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Test failed at step %@." xml:space="preserve">
|
<trans-unit id="Test failed at step %@." xml:space="preserve">
|
||||||
<source>Test failed at step %@.</source>
|
<source>Test failed at step %@.</source>
|
||||||
<target>La prueba ha fallado en el paso %@.</target>
|
<target>Prueba no superada en el paso %@.</target>
|
||||||
<note>server test failure</note>
|
<note>server test failure</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Test server" xml:space="preserve">
|
<trans-unit id="Test server" xml:space="preserve">
|
||||||
@@ -6628,7 +6763,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Tests failed!" xml:space="preserve">
|
<trans-unit id="Tests failed!" xml:space="preserve">
|
||||||
<source>Tests failed!</source>
|
<source>Tests failed!</source>
|
||||||
<target>¡Pruebas fallidas!</target>
|
<target>¡Pruebas no superadas!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Thank you for installing SimpleX Chat!" xml:space="preserve">
|
<trans-unit id="Thank you for installing SimpleX Chat!" xml:space="preserve">
|
||||||
@@ -6760,6 +6895,7 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
|
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
|
||||||
<source>The uploaded database archive will be permanently removed from the servers.</source>
|
<source>The uploaded database archive will be permanently removed from the servers.</source>
|
||||||
|
<target>El archivo de bases de datos subido será eliminado permanentemente de los servidores.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Themes" xml:space="preserve">
|
<trans-unit id="Themes" xml:space="preserve">
|
||||||
@@ -6889,6 +7025,16 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||||||
Se te pedirá que completes la autenticación antes de activar esta función.</target>
|
Se te pedirá que completes la autenticación antes de activar esta función.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="To record speech please grant permission to use Microphone." xml:space="preserve">
|
||||||
|
<source>To record speech please grant permission to use Microphone.</source>
|
||||||
|
<target>Para grabación de voz, por favor concede el permiso para usar el micrófono.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="To record video please grant permission to use Camera." xml:space="preserve">
|
||||||
|
<source>To record video please grant permission to use Camera.</source>
|
||||||
|
<target>Para grabación de vídeo, por favor concede el permiso para usar la cámara.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
||||||
<source>To record voice message please grant permission to use Microphone.</source>
|
<source>To record voice message please grant permission to use Microphone.</source>
|
||||||
<target>Para grabar el mensaje de voz concede permiso para usar el micrófono.</target>
|
<target>Para grabar el mensaje de voz concede permiso para usar el micrófono.</target>
|
||||||
@@ -7158,6 +7304,7 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
|
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
|
||||||
<source>Use SOCKS proxy</source>
|
<source>Use SOCKS proxy</source>
|
||||||
|
<target>Usar proxy SOCKS</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
|
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
|
||||||
@@ -7225,11 +7372,6 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión
|
|||||||
<target>Usa la aplicación con una sola mano.</target>
|
<target>Usa la aplicación con una sola mano.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User profile" xml:space="preserve">
|
|
||||||
<source>User profile</source>
|
|
||||||
<target>Perfil de usuario</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User selection" xml:space="preserve">
|
<trans-unit id="User selection" xml:space="preserve">
|
||||||
<source>User selection</source>
|
<source>User selection</source>
|
||||||
<target>Selección de usuarios</target>
|
<target>Selección de usuarios</target>
|
||||||
@@ -7237,6 +7379,7 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Username" xml:space="preserve">
|
<trans-unit id="Username" xml:space="preserve">
|
||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
|
<target>Nombre de usuario</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
|
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
|
||||||
@@ -7499,11 +7642,6 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión
|
|||||||
<target>Servidor XFTP</target>
|
<target>Servidor XFTP</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="You" xml:space="preserve">
|
|
||||||
<source>You</source>
|
|
||||||
<target>Tú</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">
|
<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>
|
<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>
|
<target>**No debes** usar la misma base de datos en dos dispositivos.</target>
|
||||||
@@ -7855,6 +7993,7 @@ Repeat connection request?</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your chat preferences" xml:space="preserve">
|
<trans-unit id="Your chat preferences" xml:space="preserve">
|
||||||
<source>Your chat preferences</source>
|
<source>Your chat preferences</source>
|
||||||
|
<target>Tus preferencias de chat</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your chat profiles" xml:space="preserve">
|
<trans-unit id="Your chat profiles" xml:space="preserve">
|
||||||
@@ -7864,6 +8003,7 @@ Repeat connection request?</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile." xml:space="preserve">
|
<trans-unit id="Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile." xml:space="preserve">
|
||||||
<source>Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile.</source>
|
<source>Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile.</source>
|
||||||
|
<target>Tu conexión ha sido trasladada a %@ pero ha ocurrido un error inesperado al redirigirte al perfil.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your contact sent a file that is larger than currently supported maximum size (%@)." xml:space="preserve">
|
<trans-unit id="Your contact sent a file that is larger than currently supported maximum size (%@)." xml:space="preserve">
|
||||||
@@ -7883,6 +8023,7 @@ Repeat connection request?</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
|
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
|
||||||
<source>Your credentials may be sent unencrypted.</source>
|
<source>Your credentials may be sent unencrypted.</source>
|
||||||
|
<target>Tus credenciales podrían ser enviadas sin cifrar.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
|
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
|
||||||
@@ -7922,6 +8063,7 @@ Repeat connection request?</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
|
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
|
||||||
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
|
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
|
||||||
|
<target>Tu perfil ha sido modificado. Si lo guardas la actualización será enviada a todos tus contactos.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
|
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
|
||||||
@@ -7941,7 +8083,7 @@ Repeat connection request?</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your server address" xml:space="preserve">
|
<trans-unit id="Your server address" xml:space="preserve">
|
||||||
<source>Your server address</source>
|
<source>Your server address</source>
|
||||||
<target>Dirección de tu servidor</target>
|
<target>Dirección del servidor</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your settings" xml:space="preserve">
|
<trans-unit id="Your settings" xml:space="preserve">
|
||||||
@@ -8653,7 +8795,7 @@ Repeat connection request?</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="removed profile picture" xml:space="preserve">
|
<trans-unit id="removed profile picture" xml:space="preserve">
|
||||||
<source>removed profile picture</source>
|
<source>removed profile picture</source>
|
||||||
<target>imagen de perfil eliminada</target>
|
<target>ha eliminado la imagen del perfil</target>
|
||||||
<note>profile update event chat item</note>
|
<note>profile update event chat item</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="removed you" xml:space="preserve">
|
<trans-unit id="removed you" xml:space="preserve">
|
||||||
@@ -8717,7 +8859,7 @@ last received msg: %2$@</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="set new profile picture" xml:space="preserve">
|
<trans-unit id="set new profile picture" xml:space="preserve">
|
||||||
<source>set new profile picture</source>
|
<source>set new profile picture</source>
|
||||||
<target>nueva imagen de perfil</target>
|
<target>tiene nueva imagen del perfil</target>
|
||||||
<note>profile update event chat item</note>
|
<note>profile update event chat item</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="standard end-to-end encryption" xml:space="preserve">
|
<trans-unit id="standard end-to-end encryption" xml:space="preserve">
|
||||||
@@ -9065,7 +9207,7 @@ last received msg: %2$@</source>
|
|||||||
</trans-unit>
|
</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">
|
||||||
<source>Database passphrase is different from saved in the keychain.</source>
|
<source>Database passphrase is different from saved in the keychain.</source>
|
||||||
<target>La contraseña de la base de datos es distinta a la almacenada en keychain.</target>
|
<target>La contraseña de la base de datos es diferente a la almacenada en keychain.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Database passphrase is required to open chat." xml:space="preserve">
|
<trans-unit id="Database passphrase is required to open chat." xml:space="preserve">
|
||||||
|
|||||||
@@ -710,7 +710,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All profiles" xml:space="preserve">
|
<trans-unit id="All profiles" xml:space="preserve">
|
||||||
<source>All profiles</source>
|
<source>All profiles</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>profile dropdown</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||||
<source>All your contacts will remain connected.</source>
|
<source>All your contacts will remain connected.</source>
|
||||||
@@ -892,6 +892,10 @@
|
|||||||
<target>Sovelluksen pääsykoodi korvataan itsetuhoutuvalla pääsykoodilla.</target>
|
<target>Sovelluksen pääsykoodi korvataan itsetuhoutuvalla pääsykoodilla.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="App session" xml:space="preserve">
|
||||||
|
<source>App session</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="App version" xml:space="preserve">
|
<trans-unit id="App version" xml:space="preserve">
|
||||||
<source>App version</source>
|
<source>App version</source>
|
||||||
<target>Sovellusversio</target>
|
<target>Sovellusversio</target>
|
||||||
@@ -1018,10 +1022,18 @@
|
|||||||
<target>Virheellinen viestin tarkiste</target>
|
<target>Virheellinen viestin tarkiste</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better calls" xml:space="preserve">
|
||||||
|
<source>Better calls</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better groups" xml:space="preserve">
|
<trans-unit id="Better groups" xml:space="preserve">
|
||||||
<source>Better groups</source>
|
<source>Better groups</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better message dates." xml:space="preserve">
|
||||||
|
<source>Better message dates.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better messages" xml:space="preserve">
|
<trans-unit id="Better messages" xml:space="preserve">
|
||||||
<source>Better messages</source>
|
<source>Better messages</source>
|
||||||
<target>Parempia viestejä</target>
|
<target>Parempia viestejä</target>
|
||||||
@@ -1031,6 +1043,18 @@
|
|||||||
<source>Better networking</source>
|
<source>Better networking</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better notifications" xml:space="preserve">
|
||||||
|
<source>Better notifications</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||||
|
<source>Better security ✅</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better user experience" xml:space="preserve">
|
||||||
|
<source>Better user experience</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Black" xml:space="preserve">
|
<trans-unit id="Black" xml:space="preserve">
|
||||||
<source>Black</source>
|
<source>Black</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -1291,6 +1315,11 @@
|
|||||||
<source>Chat preferences were changed.</source>
|
<source>Chat preferences were changed.</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat profile" xml:space="preserve">
|
||||||
|
<source>Chat profile</source>
|
||||||
|
<target>Käyttäjäprofiili</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Chat theme" xml:space="preserve">
|
<trans-unit id="Chat theme" xml:space="preserve">
|
||||||
<source>Chat theme</source>
|
<source>Chat theme</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -1767,6 +1796,10 @@ This is your own one-time link!</source>
|
|||||||
<target>Mukautettu aika</target>
|
<target>Mukautettu aika</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Customizable message shape." xml:space="preserve">
|
||||||
|
<source>Customizable message shape.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Customize theme" xml:space="preserve">
|
<trans-unit id="Customize theme" xml:space="preserve">
|
||||||
<source>Customize theme</source>
|
<source>Customize theme</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -2053,6 +2086,10 @@ This is your own one-time link!</source>
|
|||||||
<target>Poista vanha tietokanta?</target>
|
<target>Poista vanha tietokanta?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Delete or moderate up to 200 messages." xml:space="preserve">
|
||||||
|
<source>Delete or moderate up to 200 messages.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
||||||
<source>Delete pending connection?</source>
|
<source>Delete pending connection?</source>
|
||||||
<target>Poistetaanko odottava yhteys?</target>
|
<target>Poistetaanko odottava yhteys?</target>
|
||||||
@@ -2826,7 +2863,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error switching profile!" xml:space="preserve">
|
<trans-unit id="Error switching profile!" xml:space="preserve">
|
||||||
<source>Error switching profile!</source>
|
<source>Error switching profile!</source>
|
||||||
<target>Virhe profiilin vaihdossa!</target>
|
<target>Virhe profiilin vaihdossa!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>alertTitle</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
||||||
<source>Error synchronizing connection</source>
|
<source>Error synchronizing connection</source>
|
||||||
@@ -2869,8 +2906,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>Virhe: %@</target>
|
<target>Virhe: %@</target>
|
||||||
<note>file error text
|
<note>alert message</note>
|
||||||
snd error text</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
||||||
<source>Error: URL is invalid</source>
|
<source>Error: URL is invalid</source>
|
||||||
@@ -3098,6 +3134,10 @@ This is your own one-time link!</source>
|
|||||||
<source>Forward messages without files?</source>
|
<source>Forward messages without files?</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Forward up to 20 messages at once." xml:space="preserve">
|
||||||
|
<source>Forward up to 20 messages at once.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Forwarded" xml:space="preserve">
|
<trans-unit id="Forwarded" xml:space="preserve">
|
||||||
<source>Forwarded</source>
|
<source>Forwarded</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -3464,6 +3504,11 @@ Error: %2$@</source>
|
|||||||
<source>Importing archive</source>
|
<source>Importing archive</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Improved delivery, reduced traffic usage. More improvements are coming soon!" xml:space="preserve">
|
||||||
|
<source>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Improved message delivery" xml:space="preserve">
|
<trans-unit id="Improved message delivery" xml:space="preserve">
|
||||||
<source>Improved message delivery</source>
|
<source>Improved message delivery</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -4192,6 +4237,14 @@ This is your link for group %@!</source>
|
|||||||
<target>Uusi pääsykoodi</target>
|
<target>Uusi pääsykoodi</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used every time you start the app." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used every time you start the app.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used for each server." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used for each server.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="New chat" xml:space="preserve">
|
<trans-unit id="New chat" xml:space="preserve">
|
||||||
<source>New chat</source>
|
<source>New chat</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -4305,6 +4358,14 @@ This is your link for group %@!</source>
|
|||||||
<source>No network connection</source>
|
<source>No network connection</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record speech" xml:space="preserve">
|
||||||
|
<source>No permission to record speech</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record video" xml:space="preserve">
|
||||||
|
<source>No permission to record video</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
||||||
<source>No permission to record voice message</source>
|
<source>No permission to record voice message</source>
|
||||||
<target>Ei lupaa ääniviestin tallentamiseen</target>
|
<target>Ei lupaa ääniviestin tallentamiseen</target>
|
||||||
@@ -5666,6 +5727,10 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<source>Sent via proxy</source>
|
<source>Sent via proxy</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Server address" xml:space="preserve">
|
<trans-unit id="Server address" xml:space="preserve">
|
||||||
<source>Server address</source>
|
<source>Server address</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -5942,6 +6007,10 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>SimpleX-kertakutsu</target>
|
<target>SimpleX-kertakutsu</target>
|
||||||
<note>simplex link type</note>
|
<note>simplex link type</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SimpleX protocols reviewed by Trail of Bits." xml:space="preserve">
|
||||||
|
<source>SimpleX protocols reviewed by Trail of Bits.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
||||||
<source>Simplified incognito mode</source>
|
<source>Simplified incognito mode</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -6101,6 +6170,14 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>SimpleX Chat tuki</target>
|
<target>SimpleX Chat tuki</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch audio and video during the call." xml:space="preserve">
|
||||||
|
<source>Switch audio and video during the call.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch chat profile for 1-time invitations." xml:space="preserve">
|
||||||
|
<source>Switch chat profile for 1-time invitations.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="System" xml:space="preserve">
|
<trans-unit id="System" xml:space="preserve">
|
||||||
<source>System</source>
|
<source>System</source>
|
||||||
<target>Järjestelmä</target>
|
<target>Järjestelmä</target>
|
||||||
@@ -6442,6 +6519,14 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||||||
Sinua kehotetaan suorittamaan todennus loppuun, ennen kuin tämä ominaisuus otetaan käyttöön.</target>
|
Sinua kehotetaan suorittamaan todennus loppuun, ennen kuin tämä ominaisuus otetaan käyttöön.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="To record speech please grant permission to use Microphone." xml:space="preserve">
|
||||||
|
<source>To record speech please grant permission to use Microphone.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="To record video please grant permission to use Camera." xml:space="preserve">
|
||||||
|
<source>To record video please grant permission to use Camera.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
||||||
<source>To record voice message please grant permission to use Microphone.</source>
|
<source>To record voice message please grant permission to use Microphone.</source>
|
||||||
<target>Jos haluat nauhoittaa ääniviestin, anna lupa käyttää mikrofonia.</target>
|
<target>Jos haluat nauhoittaa ääniviestin, anna lupa käyttää mikrofonia.</target>
|
||||||
@@ -6751,11 +6836,6 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja
|
|||||||
<source>Use the app with one hand.</source>
|
<source>Use the app with one hand.</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User profile" xml:space="preserve">
|
|
||||||
<source>User profile</source>
|
|
||||||
<target>Käyttäjäprofiili</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User selection" xml:space="preserve">
|
<trans-unit id="User selection" xml:space="preserve">
|
||||||
<source>User selection</source>
|
<source>User selection</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -7000,11 +7080,6 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja
|
|||||||
<source>XFTP server</source>
|
<source>XFTP server</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="You" xml:space="preserve">
|
|
||||||
<source>You</source>
|
|
||||||
<target>Sinä</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">
|
<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>
|
<source>You **must not** use the same database on two devices.</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
|
|||||||
@@ -747,7 +747,7 @@
|
|||||||
<trans-unit id="All profiles" xml:space="preserve">
|
<trans-unit id="All profiles" xml:space="preserve">
|
||||||
<source>All profiles</source>
|
<source>All profiles</source>
|
||||||
<target>Tous les profiles</target>
|
<target>Tous les profiles</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>profile dropdown</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||||
<source>All your contacts will remain connected.</source>
|
<source>All your contacts will remain connected.</source>
|
||||||
@@ -939,6 +939,10 @@
|
|||||||
<target>Le code d'accès de l'application est remplacé par un code d'autodestruction.</target>
|
<target>Le code d'accès de l'application est remplacé par un code d'autodestruction.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="App session" xml:space="preserve">
|
||||||
|
<source>App session</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="App version" xml:space="preserve">
|
<trans-unit id="App version" xml:space="preserve">
|
||||||
<source>App version</source>
|
<source>App version</source>
|
||||||
<target>Version de l'app</target>
|
<target>Version de l'app</target>
|
||||||
@@ -1073,11 +1077,19 @@
|
|||||||
<target>Mauvais hash de message</target>
|
<target>Mauvais hash de message</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better calls" xml:space="preserve">
|
||||||
|
<source>Better calls</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better groups" xml:space="preserve">
|
<trans-unit id="Better groups" xml:space="preserve">
|
||||||
<source>Better groups</source>
|
<source>Better groups</source>
|
||||||
<target>Des groupes plus performants</target>
|
<target>Des groupes plus performants</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better message dates." xml:space="preserve">
|
||||||
|
<source>Better message dates.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better messages" xml:space="preserve">
|
<trans-unit id="Better messages" xml:space="preserve">
|
||||||
<source>Better messages</source>
|
<source>Better messages</source>
|
||||||
<target>Meilleurs messages</target>
|
<target>Meilleurs messages</target>
|
||||||
@@ -1088,6 +1100,18 @@
|
|||||||
<target>Meilleure gestion de réseau</target>
|
<target>Meilleure gestion de réseau</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better notifications" xml:space="preserve">
|
||||||
|
<source>Better notifications</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||||
|
<source>Better security ✅</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better user experience" xml:space="preserve">
|
||||||
|
<source>Better user experience</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Black" xml:space="preserve">
|
<trans-unit id="Black" xml:space="preserve">
|
||||||
<source>Black</source>
|
<source>Black</source>
|
||||||
<target>Noir</target>
|
<target>Noir</target>
|
||||||
@@ -1373,6 +1397,11 @@
|
|||||||
<source>Chat preferences were changed.</source>
|
<source>Chat preferences were changed.</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat profile" xml:space="preserve">
|
||||||
|
<source>Chat profile</source>
|
||||||
|
<target>Profil d'utilisateur</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Chat theme" xml:space="preserve">
|
<trans-unit id="Chat theme" xml:space="preserve">
|
||||||
<source>Chat theme</source>
|
<source>Chat theme</source>
|
||||||
<target>Thème de chat</target>
|
<target>Thème de chat</target>
|
||||||
@@ -1901,6 +1930,10 @@ Il s'agit de votre propre lien unique !</target>
|
|||||||
<target>Délai personnalisé</target>
|
<target>Délai personnalisé</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Customizable message shape." xml:space="preserve">
|
||||||
|
<source>Customizable message shape.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Customize theme" xml:space="preserve">
|
<trans-unit id="Customize theme" xml:space="preserve">
|
||||||
<source>Customize theme</source>
|
<source>Customize theme</source>
|
||||||
<target>Personnaliser le thème</target>
|
<target>Personnaliser le thème</target>
|
||||||
@@ -2195,6 +2228,10 @@ Il s'agit de votre propre lien unique !</target>
|
|||||||
<target>Supprimer l'ancienne base de données ?</target>
|
<target>Supprimer l'ancienne base de données ?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Delete or moderate up to 200 messages." xml:space="preserve">
|
||||||
|
<source>Delete or moderate up to 200 messages.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
||||||
<source>Delete pending connection?</source>
|
<source>Delete pending connection?</source>
|
||||||
<target>Supprimer la connexion en attente ?</target>
|
<target>Supprimer la connexion en attente ?</target>
|
||||||
@@ -3018,7 +3055,7 @@ Il s'agit de votre propre lien unique !</target>
|
|||||||
<trans-unit id="Error switching profile!" xml:space="preserve">
|
<trans-unit id="Error switching profile!" xml:space="preserve">
|
||||||
<source>Error switching profile!</source>
|
<source>Error switching profile!</source>
|
||||||
<target>Erreur lors du changement de profil !</target>
|
<target>Erreur lors du changement de profil !</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>alertTitle</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
||||||
<source>Error synchronizing connection</source>
|
<source>Error synchronizing connection</source>
|
||||||
@@ -3063,8 +3100,7 @@ Il s'agit de votre propre lien unique !</target>
|
|||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>Erreur : %@</target>
|
<target>Erreur : %@</target>
|
||||||
<note>file error text
|
<note>alert message</note>
|
||||||
snd error text</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
||||||
<source>Error: URL is invalid</source>
|
<source>Error: URL is invalid</source>
|
||||||
@@ -3308,6 +3344,10 @@ Il s'agit de votre propre lien unique !</target>
|
|||||||
<source>Forward messages without files?</source>
|
<source>Forward messages without files?</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Forward up to 20 messages at once." xml:space="preserve">
|
||||||
|
<source>Forward up to 20 messages at once.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Forwarded" xml:space="preserve">
|
<trans-unit id="Forwarded" xml:space="preserve">
|
||||||
<source>Forwarded</source>
|
<source>Forwarded</source>
|
||||||
<target>Transféré</target>
|
<target>Transféré</target>
|
||||||
@@ -3695,6 +3735,11 @@ Erreur : %2$@</target>
|
|||||||
<target>Importation de l'archive</target>
|
<target>Importation de l'archive</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Improved delivery, reduced traffic usage. More improvements are coming soon!" xml:space="preserve">
|
||||||
|
<source>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Improved message delivery" xml:space="preserve">
|
<trans-unit id="Improved message delivery" xml:space="preserve">
|
||||||
<source>Improved message delivery</source>
|
<source>Improved message delivery</source>
|
||||||
<target>Amélioration de la transmission des messages</target>
|
<target>Amélioration de la transmission des messages</target>
|
||||||
@@ -4478,6 +4523,14 @@ Voici votre lien pour le groupe %@ !</target>
|
|||||||
<target>Nouveau code d'accès</target>
|
<target>Nouveau code d'accès</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used every time you start the app." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used every time you start the app.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used for each server." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used for each server.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="New chat" xml:space="preserve">
|
<trans-unit id="New chat" xml:space="preserve">
|
||||||
<source>New chat</source>
|
<source>New chat</source>
|
||||||
<target>Nouveau chat</target>
|
<target>Nouveau chat</target>
|
||||||
@@ -4598,6 +4651,14 @@ Voici votre lien pour le groupe %@ !</target>
|
|||||||
<target>Pas de connexion au réseau</target>
|
<target>Pas de connexion au réseau</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record speech" xml:space="preserve">
|
||||||
|
<source>No permission to record speech</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record video" xml:space="preserve">
|
||||||
|
<source>No permission to record video</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
||||||
<source>No permission to record voice message</source>
|
<source>No permission to record voice message</source>
|
||||||
<target>Pas l'autorisation d'enregistrer un message vocal</target>
|
<target>Pas l'autorisation d'enregistrer un message vocal</target>
|
||||||
@@ -6055,6 +6116,10 @@ Activez-le dans les paramètres *Réseau et serveurs*.</target>
|
|||||||
<target>Envoyé via le proxy</target>
|
<target>Envoyé via le proxy</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Server address" xml:space="preserve">
|
<trans-unit id="Server address" xml:space="preserve">
|
||||||
<source>Server address</source>
|
<source>Server address</source>
|
||||||
<target>Adresse du serveur</target>
|
<target>Adresse du serveur</target>
|
||||||
@@ -6353,6 +6418,10 @@ Activez-le dans les paramètres *Réseau et serveurs*.</target>
|
|||||||
<target>Invitation unique SimpleX</target>
|
<target>Invitation unique SimpleX</target>
|
||||||
<note>simplex link type</note>
|
<note>simplex link type</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SimpleX protocols reviewed by Trail of Bits." xml:space="preserve">
|
||||||
|
<source>SimpleX protocols reviewed by Trail of Bits.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
||||||
<source>Simplified incognito mode</source>
|
<source>Simplified incognito mode</source>
|
||||||
<target>Mode incognito simplifié</target>
|
<target>Mode incognito simplifié</target>
|
||||||
@@ -6527,6 +6596,14 @@ Activez-le dans les paramètres *Réseau et serveurs*.</target>
|
|||||||
<target>Supporter SimpleX Chat</target>
|
<target>Supporter SimpleX Chat</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch audio and video during the call." xml:space="preserve">
|
||||||
|
<source>Switch audio and video during the call.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch chat profile for 1-time invitations." xml:space="preserve">
|
||||||
|
<source>Switch chat profile for 1-time invitations.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="System" xml:space="preserve">
|
<trans-unit id="System" xml:space="preserve">
|
||||||
<source>System</source>
|
<source>System</source>
|
||||||
<target>Système</target>
|
<target>Système</target>
|
||||||
@@ -6889,6 +6966,14 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||||||
Vous serez invité à confirmer l'authentification avant que cette fonction ne soit activée.</target>
|
Vous serez invité à confirmer l'authentification avant que cette fonction ne soit activée.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="To record speech please grant permission to use Microphone." xml:space="preserve">
|
||||||
|
<source>To record speech please grant permission to use Microphone.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="To record video please grant permission to use Camera." xml:space="preserve">
|
||||||
|
<source>To record video please grant permission to use Camera.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
||||||
<source>To record voice message please grant permission to use Microphone.</source>
|
<source>To record voice message please grant permission to use Microphone.</source>
|
||||||
<target>Pour enregistrer un message vocal, veuillez accorder la permission d'utiliser le microphone.</target>
|
<target>Pour enregistrer un message vocal, veuillez accorder la permission d'utiliser le microphone.</target>
|
||||||
@@ -7225,11 +7310,6 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
|
|||||||
<target>Utiliser l'application d'une main.</target>
|
<target>Utiliser l'application d'une main.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User profile" xml:space="preserve">
|
|
||||||
<source>User profile</source>
|
|
||||||
<target>Profil d'utilisateur</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User selection" xml:space="preserve">
|
<trans-unit id="User selection" xml:space="preserve">
|
||||||
<source>User selection</source>
|
<source>User selection</source>
|
||||||
<target>Sélection de l'utilisateur</target>
|
<target>Sélection de l'utilisateur</target>
|
||||||
@@ -7499,11 +7579,6 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
|
|||||||
<target>Serveur XFTP</target>
|
<target>Serveur XFTP</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="You" xml:space="preserve">
|
|
||||||
<source>You</source>
|
|
||||||
<target>Vous</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">
|
<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>
|
<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>
|
<target>Vous **ne devez pas** utiliser la même base de données sur deux appareils.</target>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -164,18 +164,22 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
|
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
|
||||||
<source>%d file(s) are still being downloaded.</source>
|
<source>%d file(s) are still being downloaded.</source>
|
||||||
|
<target>%d file è/sono ancora in scaricamento.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
|
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
|
||||||
<source>%d file(s) failed to download.</source>
|
<source>%d file(s) failed to download.</source>
|
||||||
|
<target>%d file ha/hanno fallito lo scaricamento.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
|
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
|
||||||
<source>%d file(s) were deleted.</source>
|
<source>%d file(s) were deleted.</source>
|
||||||
|
<target>%d file è/sono stato/i eliminato/i.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
|
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
|
||||||
<source>%d file(s) were not downloaded.</source>
|
<source>%d file(s) were not downloaded.</source>
|
||||||
|
<target>%d file non è/sono stato/i scaricato/i.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d hours" xml:space="preserve">
|
<trans-unit id="%d hours" xml:space="preserve">
|
||||||
@@ -185,6 +189,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d messages not forwarded" xml:space="preserve">
|
<trans-unit id="%d messages not forwarded" xml:space="preserve">
|
||||||
<source>%d messages not forwarded</source>
|
<source>%d messages not forwarded</source>
|
||||||
|
<target>%d messaggi non inoltrati</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d min" xml:space="preserve">
|
<trans-unit id="%d min" xml:space="preserve">
|
||||||
@@ -748,7 +753,7 @@
|
|||||||
<trans-unit id="All profiles" xml:space="preserve">
|
<trans-unit id="All profiles" xml:space="preserve">
|
||||||
<source>All profiles</source>
|
<source>All profiles</source>
|
||||||
<target>Tutti gli profili</target>
|
<target>Tutti gli profili</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>profile dropdown</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||||
<source>All your contacts will remain connected.</source>
|
<source>All your contacts will remain connected.</source>
|
||||||
@@ -940,6 +945,11 @@
|
|||||||
<target>Il codice di accesso dell'app viene sostituito da un codice di autodistruzione.</target>
|
<target>Il codice di accesso dell'app viene sostituito da un codice di autodistruzione.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="App session" xml:space="preserve">
|
||||||
|
<source>App session</source>
|
||||||
|
<target>Sessione dell'app</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="App version" xml:space="preserve">
|
<trans-unit id="App version" xml:space="preserve">
|
||||||
<source>App version</source>
|
<source>App version</source>
|
||||||
<target>Versione dell'app</target>
|
<target>Versione dell'app</target>
|
||||||
@@ -1075,11 +1085,21 @@
|
|||||||
<target>Hash del messaggio errato</target>
|
<target>Hash del messaggio errato</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better calls" xml:space="preserve">
|
||||||
|
<source>Better calls</source>
|
||||||
|
<target>Chiamate migliorate</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better groups" xml:space="preserve">
|
<trans-unit id="Better groups" xml:space="preserve">
|
||||||
<source>Better groups</source>
|
<source>Better groups</source>
|
||||||
<target>Gruppi migliorati</target>
|
<target>Gruppi migliorati</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better message dates." xml:space="preserve">
|
||||||
|
<source>Better message dates.</source>
|
||||||
|
<target>Date dei messaggi migliorate.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better messages" xml:space="preserve">
|
<trans-unit id="Better messages" xml:space="preserve">
|
||||||
<source>Better messages</source>
|
<source>Better messages</source>
|
||||||
<target>Messaggi migliorati</target>
|
<target>Messaggi migliorati</target>
|
||||||
@@ -1090,6 +1110,21 @@
|
|||||||
<target>Rete migliorata</target>
|
<target>Rete migliorata</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better notifications" xml:space="preserve">
|
||||||
|
<source>Better notifications</source>
|
||||||
|
<target>Notifiche migliorate</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||||
|
<source>Better security ✅</source>
|
||||||
|
<target>Sicurezza migliorata ✅</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better user experience" xml:space="preserve">
|
||||||
|
<source>Better user experience</source>
|
||||||
|
<target>Esperienza utente migliorata</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Black" xml:space="preserve">
|
<trans-unit id="Black" xml:space="preserve">
|
||||||
<source>Black</source>
|
<source>Black</source>
|
||||||
<target>Nero</target>
|
<target>Nero</target>
|
||||||
@@ -1376,6 +1411,11 @@
|
|||||||
<target>Le preferenze della chat sono state cambiate.</target>
|
<target>Le preferenze della chat sono state cambiate.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat profile" xml:space="preserve">
|
||||||
|
<source>Chat profile</source>
|
||||||
|
<target>Profilo utente</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Chat theme" xml:space="preserve">
|
<trans-unit id="Chat theme" xml:space="preserve">
|
||||||
<source>Chat theme</source>
|
<source>Chat theme</source>
|
||||||
<target>Tema della chat</target>
|
<target>Tema della chat</target>
|
||||||
@@ -1905,6 +1945,11 @@ Questo è il tuo link una tantum!</target>
|
|||||||
<target>Tempo personalizzato</target>
|
<target>Tempo personalizzato</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Customizable message shape." xml:space="preserve">
|
||||||
|
<source>Customizable message shape.</source>
|
||||||
|
<target>Forma dei messaggi personalizzabile.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Customize theme" xml:space="preserve">
|
<trans-unit id="Customize theme" xml:space="preserve">
|
||||||
<source>Customize theme</source>
|
<source>Customize theme</source>
|
||||||
<target>Personalizza il tema</target>
|
<target>Personalizza il tema</target>
|
||||||
@@ -2199,6 +2244,11 @@ Questo è il tuo link una tantum!</target>
|
|||||||
<target>Eliminare il database vecchio?</target>
|
<target>Eliminare il database vecchio?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Delete or moderate up to 200 messages." xml:space="preserve">
|
||||||
|
<source>Delete or moderate up to 200 messages.</source>
|
||||||
|
<target>Elimina o modera fino a 200 messaggi.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
||||||
<source>Delete pending connection?</source>
|
<source>Delete pending connection?</source>
|
||||||
<target>Eliminare la connessione in attesa?</target>
|
<target>Eliminare la connessione in attesa?</target>
|
||||||
@@ -2451,6 +2501,7 @@ Questo è il tuo link una tantum!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
|
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
|
||||||
<source>Do not use credentials with proxy.</source>
|
<source>Do not use credentials with proxy.</source>
|
||||||
|
<target>Non usare credenziali con proxy.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Don't create address" xml:space="preserve">
|
<trans-unit id="Don't create address" xml:space="preserve">
|
||||||
@@ -2496,6 +2547,7 @@ Questo è il tuo link una tantum!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Download files" xml:space="preserve">
|
<trans-unit id="Download files" xml:space="preserve">
|
||||||
<source>Download files</source>
|
<source>Download files</source>
|
||||||
|
<target>Scarica i file</target>
|
||||||
<note>alert action</note>
|
<note>alert action</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Downloaded" xml:space="preserve">
|
<trans-unit id="Downloaded" xml:space="preserve">
|
||||||
@@ -3026,7 +3078,7 @@ Questo è il tuo link una tantum!</target>
|
|||||||
<trans-unit id="Error switching profile!" xml:space="preserve">
|
<trans-unit id="Error switching profile!" xml:space="preserve">
|
||||||
<source>Error switching profile!</source>
|
<source>Error switching profile!</source>
|
||||||
<target>Errore nel cambio di profilo!</target>
|
<target>Errore nel cambio di profilo!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>alertTitle</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
||||||
<source>Error synchronizing connection</source>
|
<source>Error synchronizing connection</source>
|
||||||
@@ -3071,8 +3123,7 @@ Questo è il tuo link una tantum!</target>
|
|||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>Errore: %@</target>
|
<target>Errore: %@</target>
|
||||||
<note>file error text
|
<note>alert message</note>
|
||||||
snd error text</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
||||||
<source>Error: URL is invalid</source>
|
<source>Error: URL is invalid</source>
|
||||||
@@ -3162,6 +3213,8 @@ Questo è il tuo link una tantum!</target>
|
|||||||
<trans-unit id="File errors: %@" xml:space="preserve">
|
<trans-unit id="File errors: %@" xml:space="preserve">
|
||||||
<source>File errors:
|
<source>File errors:
|
||||||
%@</source>
|
%@</source>
|
||||||
|
<target>Errori di file:
|
||||||
|
%@</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||||
@@ -3301,6 +3354,7 @@ Questo è il tuo link una tantum!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
|
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
|
||||||
<source>Forward %d message(s)?</source>
|
<source>Forward %d message(s)?</source>
|
||||||
|
<target>Inoltrare %d messaggio/i?</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward and save messages" xml:space="preserve">
|
<trans-unit id="Forward and save messages" xml:space="preserve">
|
||||||
@@ -3310,12 +3364,19 @@ Questo è il tuo link una tantum!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward messages" xml:space="preserve">
|
<trans-unit id="Forward messages" xml:space="preserve">
|
||||||
<source>Forward messages</source>
|
<source>Forward messages</source>
|
||||||
|
<target>Inoltra i messaggi</target>
|
||||||
<note>alert action</note>
|
<note>alert action</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward messages without files?" xml:space="preserve">
|
<trans-unit id="Forward messages without files?" xml:space="preserve">
|
||||||
<source>Forward messages without files?</source>
|
<source>Forward messages without files?</source>
|
||||||
|
<target>Inoltrare i messaggi senza file?</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Forward up to 20 messages at once." xml:space="preserve">
|
||||||
|
<source>Forward up to 20 messages at once.</source>
|
||||||
|
<target>Inoltra fino a 20 messaggi alla volta.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Forwarded" xml:space="preserve">
|
<trans-unit id="Forwarded" xml:space="preserve">
|
||||||
<source>Forwarded</source>
|
<source>Forwarded</source>
|
||||||
<target>Inoltrato</target>
|
<target>Inoltrato</target>
|
||||||
@@ -3328,6 +3389,7 @@ Questo è il tuo link una tantum!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
|
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
|
||||||
<source>Forwarding %lld messages</source>
|
<source>Forwarding %lld messages</source>
|
||||||
|
<target>Inoltro di %lld messaggi</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
|
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
|
||||||
@@ -3626,6 +3688,7 @@ Errore: %2$@</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="IP address" xml:space="preserve">
|
<trans-unit id="IP address" xml:space="preserve">
|
||||||
<source>IP address</source>
|
<source>IP address</source>
|
||||||
|
<target>Indirizzo IP</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
|
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
|
||||||
@@ -3703,6 +3766,13 @@ Errore: %2$@</target>
|
|||||||
<target>Importazione archivio</target>
|
<target>Importazione archivio</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Improved delivery, reduced traffic usage. More improvements are coming soon!" xml:space="preserve">
|
||||||
|
<source>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</source>
|
||||||
|
<target>Consegna migliorata, utilizzo di traffico ridotto.
|
||||||
|
Altri miglioramenti sono in arrivo!</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Improved message delivery" xml:space="preserve">
|
<trans-unit id="Improved message delivery" xml:space="preserve">
|
||||||
<source>Improved message delivery</source>
|
<source>Improved message delivery</source>
|
||||||
<target>Consegna dei messaggi migliorata</target>
|
<target>Consegna dei messaggi migliorata</target>
|
||||||
@@ -4330,6 +4400,7 @@ Questo è il tuo link per il gruppo %@!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
|
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
|
||||||
<source>Messages were deleted after you selected them.</source>
|
<source>Messages were deleted after you selected them.</source>
|
||||||
|
<target>I messaggi sono stati eliminati dopo che li hai selezionati.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</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">
|
<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">
|
||||||
@@ -4487,6 +4558,16 @@ Questo è il tuo link per il gruppo %@!</target>
|
|||||||
<target>Nuovo codice di accesso</target>
|
<target>Nuovo codice di accesso</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used every time you start the app." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used every time you start the app.</source>
|
||||||
|
<target>Le nuove credenziali SOCKS verranno usate ogni volta che avvii l'app.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used for each server." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used for each server.</source>
|
||||||
|
<target>Le nuove credenziali SOCKS verranno usate per ogni server.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="New chat" xml:space="preserve">
|
<trans-unit id="New chat" xml:space="preserve">
|
||||||
<source>New chat</source>
|
<source>New chat</source>
|
||||||
<target>Nuova chat</target>
|
<target>Nuova chat</target>
|
||||||
@@ -4607,6 +4688,16 @@ Questo è il tuo link per il gruppo %@!</target>
|
|||||||
<target>Nessuna connessione di rete</target>
|
<target>Nessuna connessione di rete</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record speech" xml:space="preserve">
|
||||||
|
<source>No permission to record speech</source>
|
||||||
|
<target>Nessuna autorizzazione per registrare l'audio</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record video" xml:space="preserve">
|
||||||
|
<source>No permission to record video</source>
|
||||||
|
<target>Nessuna autorizzazione per registrare il video</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
||||||
<source>No permission to record voice message</source>
|
<source>No permission to record voice message</source>
|
||||||
<target>Nessuna autorizzazione per registrare messaggi vocali</target>
|
<target>Nessuna autorizzazione per registrare messaggi vocali</target>
|
||||||
@@ -4629,6 +4720,7 @@ Questo è il tuo link per il gruppo %@!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Nothing to forward!" xml:space="preserve">
|
<trans-unit id="Nothing to forward!" xml:space="preserve">
|
||||||
<source>Nothing to forward!</source>
|
<source>Nothing to forward!</source>
|
||||||
|
<target>Niente da inoltrare!</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Notifications" xml:space="preserve">
|
<trans-unit id="Notifications" xml:space="preserve">
|
||||||
@@ -4857,6 +4949,8 @@ Richiede l'attivazione della VPN.</target>
|
|||||||
<trans-unit id="Other file errors: %@" xml:space="preserve">
|
<trans-unit id="Other file errors: %@" xml:space="preserve">
|
||||||
<source>Other file errors:
|
<source>Other file errors:
|
||||||
%@</source>
|
%@</source>
|
||||||
|
<target>Altri errori di file:
|
||||||
|
%@</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="PING count" xml:space="preserve">
|
<trans-unit id="PING count" xml:space="preserve">
|
||||||
@@ -4896,6 +4990,7 @@ Richiede l'attivazione della VPN.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Password" xml:space="preserve">
|
<trans-unit id="Password" xml:space="preserve">
|
||||||
<source>Password</source>
|
<source>Password</source>
|
||||||
|
<target>Password</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Password to show" xml:space="preserve">
|
<trans-unit id="Password to show" xml:space="preserve">
|
||||||
@@ -5049,6 +5144,7 @@ Errore: %@</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Port" xml:space="preserve">
|
<trans-unit id="Port" xml:space="preserve">
|
||||||
<source>Port</source>
|
<source>Port</source>
|
||||||
|
<target>Porta</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
|
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
|
||||||
@@ -5240,6 +5336,7 @@ Attivalo nelle impostazioni *Rete e server*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Proxy requires password" xml:space="preserve">
|
<trans-unit id="Proxy requires password" xml:space="preserve">
|
||||||
<source>Proxy requires password</source>
|
<source>Proxy requires password</source>
|
||||||
|
<target>Il proxy richiede una password</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Push notifications" xml:space="preserve">
|
<trans-unit id="Push notifications" xml:space="preserve">
|
||||||
@@ -5650,6 +5747,7 @@ Attivalo nelle impostazioni *Rete e server*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="SOCKS proxy" xml:space="preserve">
|
<trans-unit id="SOCKS proxy" xml:space="preserve">
|
||||||
<source>SOCKS proxy</source>
|
<source>SOCKS proxy</source>
|
||||||
|
<target>Proxy SOCKS</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Safely receive files" xml:space="preserve">
|
<trans-unit id="Safely receive files" xml:space="preserve">
|
||||||
@@ -5765,6 +5863,7 @@ Attivalo nelle impostazioni *Rete e server*.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Saving %lld messages" xml:space="preserve">
|
<trans-unit id="Saving %lld messages" xml:space="preserve">
|
||||||
<source>Saving %lld messages</source>
|
<source>Saving %lld messages</source>
|
||||||
|
<target>Salvataggio di %lld messaggi</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Scale" xml:space="preserve">
|
<trans-unit id="Scale" xml:space="preserve">
|
||||||
@@ -6067,6 +6166,11 @@ Attivalo nelle impostazioni *Rete e server*.</target>
|
|||||||
<target>Inviato via proxy</target>
|
<target>Inviato via proxy</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<target>Server</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Server address" xml:space="preserve">
|
<trans-unit id="Server address" xml:space="preserve">
|
||||||
<source>Server address</source>
|
<source>Server address</source>
|
||||||
<target>Indirizzo server</target>
|
<target>Indirizzo server</target>
|
||||||
@@ -6367,6 +6471,11 @@ Attivalo nelle impostazioni *Rete e server*.</target>
|
|||||||
<target>Invito SimpleX una tantum</target>
|
<target>Invito SimpleX una tantum</target>
|
||||||
<note>simplex link type</note>
|
<note>simplex link type</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SimpleX protocols reviewed by Trail of Bits." xml:space="preserve">
|
||||||
|
<source>SimpleX protocols reviewed by Trail of Bits.</source>
|
||||||
|
<target>Protocolli di SimpleX esaminati da Trail of Bits.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
||||||
<source>Simplified incognito mode</source>
|
<source>Simplified incognito mode</source>
|
||||||
<target>Modalità incognito semplificata</target>
|
<target>Modalità incognito semplificata</target>
|
||||||
@@ -6542,6 +6651,16 @@ Attivalo nelle impostazioni *Rete e server*.</target>
|
|||||||
<target>Supporta SimpleX Chat</target>
|
<target>Supporta SimpleX Chat</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch audio and video during the call." xml:space="preserve">
|
||||||
|
<source>Switch audio and video during the call.</source>
|
||||||
|
<target>Cambia tra audio e video durante la chiamata.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch chat profile for 1-time invitations." xml:space="preserve">
|
||||||
|
<source>Switch chat profile for 1-time invitations.</source>
|
||||||
|
<target>Cambia profilo di chat per inviti una tantum.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="System" xml:space="preserve">
|
<trans-unit id="System" xml:space="preserve">
|
||||||
<source>System</source>
|
<source>System</source>
|
||||||
<target>Sistema</target>
|
<target>Sistema</target>
|
||||||
@@ -6906,6 +7025,16 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||||||
Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzionalità.</target>
|
Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzionalità.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="To record speech please grant permission to use Microphone." xml:space="preserve">
|
||||||
|
<source>To record speech please grant permission to use Microphone.</source>
|
||||||
|
<target>Per registrare l'audio, concedi l'autorizzazione di usare il microfono.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="To record video please grant permission to use Camera." xml:space="preserve">
|
||||||
|
<source>To record video please grant permission to use Camera.</source>
|
||||||
|
<target>Per registrare il video, concedi l'autorizzazione di usare la fotocamera.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
||||||
<source>To record voice message please grant permission to use Microphone.</source>
|
<source>To record voice message please grant permission to use Microphone.</source>
|
||||||
<target>Per registrare un messaggio vocale, concedi l'autorizzazione all'uso del microfono.</target>
|
<target>Per registrare un messaggio vocale, concedi l'autorizzazione all'uso del microfono.</target>
|
||||||
@@ -7175,6 +7304,7 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
|
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
|
||||||
<source>Use SOCKS proxy</source>
|
<source>Use SOCKS proxy</source>
|
||||||
|
<target>Usa proxy SOCKS</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
|
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
|
||||||
@@ -7242,11 +7372,6 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
|
|||||||
<target>Usa l'app con una mano sola.</target>
|
<target>Usa l'app con una mano sola.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User profile" xml:space="preserve">
|
|
||||||
<source>User profile</source>
|
|
||||||
<target>Profilo utente</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User selection" xml:space="preserve">
|
<trans-unit id="User selection" xml:space="preserve">
|
||||||
<source>User selection</source>
|
<source>User selection</source>
|
||||||
<target>Selezione utente</target>
|
<target>Selezione utente</target>
|
||||||
@@ -7254,6 +7379,7 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Username" xml:space="preserve">
|
<trans-unit id="Username" xml:space="preserve">
|
||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
|
<target>Nome utente</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
|
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
|
||||||
@@ -7516,11 +7642,6 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
|
|||||||
<target>Server XFTP</target>
|
<target>Server XFTP</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="You" xml:space="preserve">
|
|
||||||
<source>You</source>
|
|
||||||
<target>Tu</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">
|
<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>
|
<source>You **must not** use the same database on two devices.</source>
|
||||||
<target>**Non devi** usare lo stesso database su due dispositivi.</target>
|
<target>**Non devi** usare lo stesso database su due dispositivi.</target>
|
||||||
@@ -7902,6 +8023,7 @@ Ripetere la richiesta di connessione?</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
|
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
|
||||||
<source>Your credentials may be sent unencrypted.</source>
|
<source>Your credentials may be sent unencrypted.</source>
|
||||||
|
<target>Le credenziali potrebbero essere inviate in chiaro.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
|
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
|
||||||
@@ -8121,7 +8243,7 @@ Ripetere la richiesta di connessione?</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="changed your role to %@" xml:space="preserve">
|
<trans-unit id="changed your role to %@" xml:space="preserve">
|
||||||
<source>changed your role to %@</source>
|
<source>changed your role to %@</source>
|
||||||
<target>cambiato il tuo ruolo in %@</target>
|
<target>ha cambiato il tuo ruolo in %@</target>
|
||||||
<note>rcv group event chat item</note>
|
<note>rcv group event chat item</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="changing address for %@…" xml:space="preserve">
|
<trans-unit id="changing address for %@…" xml:space="preserve">
|
||||||
|
|||||||
@@ -727,7 +727,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All profiles" xml:space="preserve">
|
<trans-unit id="All profiles" xml:space="preserve">
|
||||||
<source>All profiles</source>
|
<source>All profiles</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>profile dropdown</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||||
<source>All your contacts will remain connected.</source>
|
<source>All your contacts will remain connected.</source>
|
||||||
@@ -915,6 +915,10 @@
|
|||||||
<target>アプリのパスコードは自己破壊パスコードに置き換えられます。</target>
|
<target>アプリのパスコードは自己破壊パスコードに置き換えられます。</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="App session" xml:space="preserve">
|
||||||
|
<source>App session</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="App version" xml:space="preserve">
|
<trans-unit id="App version" xml:space="preserve">
|
||||||
<source>App version</source>
|
<source>App version</source>
|
||||||
<target>アプリのバージョン</target>
|
<target>アプリのバージョン</target>
|
||||||
@@ -1041,10 +1045,18 @@
|
|||||||
<target>メッセージのハッシュ値問題</target>
|
<target>メッセージのハッシュ値問題</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better calls" xml:space="preserve">
|
||||||
|
<source>Better calls</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better groups" xml:space="preserve">
|
<trans-unit id="Better groups" xml:space="preserve">
|
||||||
<source>Better groups</source>
|
<source>Better groups</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better message dates." xml:space="preserve">
|
||||||
|
<source>Better message dates.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better messages" xml:space="preserve">
|
<trans-unit id="Better messages" xml:space="preserve">
|
||||||
<source>Better messages</source>
|
<source>Better messages</source>
|
||||||
<target>より良いメッセージ</target>
|
<target>より良いメッセージ</target>
|
||||||
@@ -1054,6 +1066,18 @@
|
|||||||
<source>Better networking</source>
|
<source>Better networking</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better notifications" xml:space="preserve">
|
||||||
|
<source>Better notifications</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||||
|
<source>Better security ✅</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better user experience" xml:space="preserve">
|
||||||
|
<source>Better user experience</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Black" xml:space="preserve">
|
<trans-unit id="Black" xml:space="preserve">
|
||||||
<source>Black</source>
|
<source>Black</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -1315,6 +1339,11 @@
|
|||||||
<source>Chat preferences were changed.</source>
|
<source>Chat preferences were changed.</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat profile" xml:space="preserve">
|
||||||
|
<source>Chat profile</source>
|
||||||
|
<target>ユーザープロフィール</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Chat theme" xml:space="preserve">
|
<trans-unit id="Chat theme" xml:space="preserve">
|
||||||
<source>Chat theme</source>
|
<source>Chat theme</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -1791,6 +1820,10 @@ This is your own one-time link!</source>
|
|||||||
<target>カスタム時間</target>
|
<target>カスタム時間</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Customizable message shape." xml:space="preserve">
|
||||||
|
<source>Customizable message shape.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Customize theme" xml:space="preserve">
|
<trans-unit id="Customize theme" xml:space="preserve">
|
||||||
<source>Customize theme</source>
|
<source>Customize theme</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -2077,6 +2110,10 @@ This is your own one-time link!</source>
|
|||||||
<target>古いデータベースを削除しますか?</target>
|
<target>古いデータベースを削除しますか?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Delete or moderate up to 200 messages." xml:space="preserve">
|
||||||
|
<source>Delete or moderate up to 200 messages.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
||||||
<source>Delete pending connection?</source>
|
<source>Delete pending connection?</source>
|
||||||
<target>接続待ちの接続を削除しますか?</target>
|
<target>接続待ちの接続を削除しますか?</target>
|
||||||
@@ -2851,7 +2888,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error switching profile!" xml:space="preserve">
|
<trans-unit id="Error switching profile!" xml:space="preserve">
|
||||||
<source>Error switching profile!</source>
|
<source>Error switching profile!</source>
|
||||||
<target>プロフィール切り替えにエラー発生!</target>
|
<target>プロフィール切り替えにエラー発生!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>alertTitle</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
||||||
<source>Error synchronizing connection</source>
|
<source>Error synchronizing connection</source>
|
||||||
@@ -2894,8 +2931,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>エラー : %@</target>
|
<target>エラー : %@</target>
|
||||||
<note>file error text
|
<note>alert message</note>
|
||||||
snd error text</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
||||||
<source>Error: URL is invalid</source>
|
<source>Error: URL is invalid</source>
|
||||||
@@ -3123,6 +3159,10 @@ This is your own one-time link!</source>
|
|||||||
<source>Forward messages without files?</source>
|
<source>Forward messages without files?</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Forward up to 20 messages at once." xml:space="preserve">
|
||||||
|
<source>Forward up to 20 messages at once.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Forwarded" xml:space="preserve">
|
<trans-unit id="Forwarded" xml:space="preserve">
|
||||||
<source>Forwarded</source>
|
<source>Forwarded</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -3489,6 +3529,11 @@ Error: %2$@</source>
|
|||||||
<source>Importing archive</source>
|
<source>Importing archive</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Improved delivery, reduced traffic usage. More improvements are coming soon!" xml:space="preserve">
|
||||||
|
<source>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Improved message delivery" xml:space="preserve">
|
<trans-unit id="Improved message delivery" xml:space="preserve">
|
||||||
<source>Improved message delivery</source>
|
<source>Improved message delivery</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -4076,10 +4121,12 @@ This is your link for group %@!</source>
|
|||||||
</trans-unit>
|
</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">
|
<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>
|
<source>Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery.</source>
|
||||||
|
<target>メッセージ、ファイル、通話は、前方秘匿性、否認可能性および侵入復元性を備えた**エンドツーエンドの暗号化**によって保護されます。</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</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">
|
<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>
|
<source>Messages, files and calls are protected by **quantum resistant e2e encryption** with perfect forward secrecy, repudiation and break-in recovery.</source>
|
||||||
|
<target>メッセージ、ファイル、通話は、前方秘匿性、否認可能性および侵入復元性を備えた**耐量子E2E暗号化**によって保護されます。</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Migrate device" xml:space="preserve">
|
<trans-unit id="Migrate device" xml:space="preserve">
|
||||||
@@ -4216,6 +4263,14 @@ This is your link for group %@!</source>
|
|||||||
<target>新しいパスコード</target>
|
<target>新しいパスコード</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used every time you start the app." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used every time you start the app.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used for each server." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used for each server.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="New chat" xml:space="preserve">
|
<trans-unit id="New chat" xml:space="preserve">
|
||||||
<source>New chat</source>
|
<source>New chat</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -4330,6 +4385,14 @@ This is your link for group %@!</source>
|
|||||||
<source>No network connection</source>
|
<source>No network connection</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record speech" xml:space="preserve">
|
||||||
|
<source>No permission to record speech</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record video" xml:space="preserve">
|
||||||
|
<source>No permission to record video</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
||||||
<source>No permission to record voice message</source>
|
<source>No permission to record voice message</source>
|
||||||
<target>音声メッセージを録音する権限がありません</target>
|
<target>音声メッセージを録音する権限がありません</target>
|
||||||
@@ -5684,6 +5747,10 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<source>Sent via proxy</source>
|
<source>Sent via proxy</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Server address" xml:space="preserve">
|
<trans-unit id="Server address" xml:space="preserve">
|
||||||
<source>Server address</source>
|
<source>Server address</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -5960,6 +6027,10 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>SimpleX使い捨て招待リンク</target>
|
<target>SimpleX使い捨て招待リンク</target>
|
||||||
<note>simplex link type</note>
|
<note>simplex link type</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SimpleX protocols reviewed by Trail of Bits." xml:space="preserve">
|
||||||
|
<source>SimpleX protocols reviewed by Trail of Bits.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
||||||
<source>Simplified incognito mode</source>
|
<source>Simplified incognito mode</source>
|
||||||
<target>シークレットモードの簡素化</target>
|
<target>シークレットモードの簡素化</target>
|
||||||
@@ -6120,6 +6191,14 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>Simplex Chatを支援</target>
|
<target>Simplex Chatを支援</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch audio and video during the call." xml:space="preserve">
|
||||||
|
<source>Switch audio and video during the call.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch chat profile for 1-time invitations." xml:space="preserve">
|
||||||
|
<source>Switch chat profile for 1-time invitations.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="System" xml:space="preserve">
|
<trans-unit id="System" xml:space="preserve">
|
||||||
<source>System</source>
|
<source>System</source>
|
||||||
<target>システム</target>
|
<target>システム</target>
|
||||||
@@ -6460,6 +6539,14 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||||||
オンにするには、認証ステップが行われます。</target>
|
オンにするには、認証ステップが行われます。</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="To record speech please grant permission to use Microphone." xml:space="preserve">
|
||||||
|
<source>To record speech please grant permission to use Microphone.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="To record video please grant permission to use Camera." xml:space="preserve">
|
||||||
|
<source>To record video please grant permission to use Camera.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
||||||
<source>To record voice message please grant permission to use Microphone.</source>
|
<source>To record voice message please grant permission to use Microphone.</source>
|
||||||
<target>音声メッセージを録音する場合は、マイクの使用を許可してください。</target>
|
<target>音声メッセージを録音する場合は、マイクの使用を許可してください。</target>
|
||||||
@@ -6769,11 +6856,6 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
<source>Use the app with one hand.</source>
|
<source>Use the app with one hand.</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User profile" xml:space="preserve">
|
|
||||||
<source>User profile</source>
|
|
||||||
<target>ユーザープロフィール</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User selection" xml:space="preserve">
|
<trans-unit id="User selection" xml:space="preserve">
|
||||||
<source>User selection</source>
|
<source>User selection</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -7018,11 +7100,6 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
<source>XFTP server</source>
|
<source>XFTP server</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="You" xml:space="preserve">
|
|
||||||
<source>You</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">
|
<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>
|
<source>You **must not** use the same database on two devices.</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
|
|||||||
@@ -164,18 +164,22 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
|
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
|
||||||
<source>%d file(s) are still being downloaded.</source>
|
<source>%d file(s) are still being downloaded.</source>
|
||||||
|
<target>%d bestand(en) worden nog gedownload.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
|
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
|
||||||
<source>%d file(s) failed to download.</source>
|
<source>%d file(s) failed to download.</source>
|
||||||
|
<target>%d bestand(en) konden niet worden gedownload.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
|
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
|
||||||
<source>%d file(s) were deleted.</source>
|
<source>%d file(s) were deleted.</source>
|
||||||
|
<target>%d bestand(en) zijn verwijderd.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
|
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
|
||||||
<source>%d file(s) were not downloaded.</source>
|
<source>%d file(s) were not downloaded.</source>
|
||||||
|
<target>%d bestand(en) zijn niet gedownload.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d hours" xml:space="preserve">
|
<trans-unit id="%d hours" xml:space="preserve">
|
||||||
@@ -185,6 +189,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d messages not forwarded" xml:space="preserve">
|
<trans-unit id="%d messages not forwarded" xml:space="preserve">
|
||||||
<source>%d messages not forwarded</source>
|
<source>%d messages not forwarded</source>
|
||||||
|
<target>%d berichten niet doorgestuurd</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d min" xml:space="preserve">
|
<trans-unit id="%d min" xml:space="preserve">
|
||||||
@@ -748,7 +753,7 @@
|
|||||||
<trans-unit id="All profiles" xml:space="preserve">
|
<trans-unit id="All profiles" xml:space="preserve">
|
||||||
<source>All profiles</source>
|
<source>All profiles</source>
|
||||||
<target>Alle profielen</target>
|
<target>Alle profielen</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>profile dropdown</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||||
<source>All your contacts will remain connected.</source>
|
<source>All your contacts will remain connected.</source>
|
||||||
@@ -940,6 +945,11 @@
|
|||||||
<target>De app-toegangscode wordt vervangen door een zelfvernietigings wachtwoord.</target>
|
<target>De app-toegangscode wordt vervangen door een zelfvernietigings wachtwoord.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="App session" xml:space="preserve">
|
||||||
|
<source>App session</source>
|
||||||
|
<target>Appsessie</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="App version" xml:space="preserve">
|
<trans-unit id="App version" xml:space="preserve">
|
||||||
<source>App version</source>
|
<source>App version</source>
|
||||||
<target>App versie</target>
|
<target>App versie</target>
|
||||||
@@ -1075,11 +1085,21 @@
|
|||||||
<target>Onjuiste bericht hash</target>
|
<target>Onjuiste bericht hash</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better calls" xml:space="preserve">
|
||||||
|
<source>Better calls</source>
|
||||||
|
<target>Betere gesprekken</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better groups" xml:space="preserve">
|
<trans-unit id="Better groups" xml:space="preserve">
|
||||||
<source>Better groups</source>
|
<source>Better groups</source>
|
||||||
<target>Betere groepen</target>
|
<target>Betere groepen</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better message dates." xml:space="preserve">
|
||||||
|
<source>Better message dates.</source>
|
||||||
|
<target>Betere datums voor berichten.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better messages" xml:space="preserve">
|
<trans-unit id="Better messages" xml:space="preserve">
|
||||||
<source>Better messages</source>
|
<source>Better messages</source>
|
||||||
<target>Betere berichten</target>
|
<target>Betere berichten</target>
|
||||||
@@ -1090,6 +1110,21 @@
|
|||||||
<target>Beter netwerk</target>
|
<target>Beter netwerk</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better notifications" xml:space="preserve">
|
||||||
|
<source>Better notifications</source>
|
||||||
|
<target>Betere meldingen</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||||
|
<source>Better security ✅</source>
|
||||||
|
<target>Betere beveiliging ✅</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better user experience" xml:space="preserve">
|
||||||
|
<source>Better user experience</source>
|
||||||
|
<target>Betere gebruikerservaring</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Black" xml:space="preserve">
|
<trans-unit id="Black" xml:space="preserve">
|
||||||
<source>Black</source>
|
<source>Black</source>
|
||||||
<target>Zwart</target>
|
<target>Zwart</target>
|
||||||
@@ -1376,6 +1411,11 @@
|
|||||||
<target>Chatvoorkeuren zijn gewijzigd.</target>
|
<target>Chatvoorkeuren zijn gewijzigd.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat profile" xml:space="preserve">
|
||||||
|
<source>Chat profile</source>
|
||||||
|
<target>Gebruikers profiel</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Chat theme" xml:space="preserve">
|
<trans-unit id="Chat theme" xml:space="preserve">
|
||||||
<source>Chat theme</source>
|
<source>Chat theme</source>
|
||||||
<target>Chat thema</target>
|
<target>Chat thema</target>
|
||||||
@@ -1473,7 +1513,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Completed" xml:space="preserve">
|
<trans-unit id="Completed" xml:space="preserve">
|
||||||
<source>Completed</source>
|
<source>Completed</source>
|
||||||
<target>voltooid</target>
|
<target>Voltooid</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Configure ICE servers" xml:space="preserve">
|
<trans-unit id="Configure ICE servers" xml:space="preserve">
|
||||||
@@ -1905,6 +1945,11 @@ Dit is uw eigen eenmalige link!</target>
|
|||||||
<target>Aangepaste tijd</target>
|
<target>Aangepaste tijd</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Customizable message shape." xml:space="preserve">
|
||||||
|
<source>Customizable message shape.</source>
|
||||||
|
<target>Aanpasbare berichtvorm.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Customize theme" xml:space="preserve">
|
<trans-unit id="Customize theme" xml:space="preserve">
|
||||||
<source>Customize theme</source>
|
<source>Customize theme</source>
|
||||||
<target>Thema aanpassen</target>
|
<target>Thema aanpassen</target>
|
||||||
@@ -2199,6 +2244,11 @@ Dit is uw eigen eenmalige link!</target>
|
|||||||
<target>Oude database verwijderen?</target>
|
<target>Oude database verwijderen?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Delete or moderate up to 200 messages." xml:space="preserve">
|
||||||
|
<source>Delete or moderate up to 200 messages.</source>
|
||||||
|
<target>Maximaal 200 berichten verwijderen of modereren.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
||||||
<source>Delete pending connection?</source>
|
<source>Delete pending connection?</source>
|
||||||
<target>Wachtende verbinding verwijderen?</target>
|
<target>Wachtende verbinding verwijderen?</target>
|
||||||
@@ -2451,6 +2501,7 @@ Dit is uw eigen eenmalige link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
|
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
|
||||||
<source>Do not use credentials with proxy.</source>
|
<source>Do not use credentials with proxy.</source>
|
||||||
|
<target>Gebruik geen inloggegevens met proxy.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Don't create address" xml:space="preserve">
|
<trans-unit id="Don't create address" xml:space="preserve">
|
||||||
@@ -2496,6 +2547,7 @@ Dit is uw eigen eenmalige link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Download files" xml:space="preserve">
|
<trans-unit id="Download files" xml:space="preserve">
|
||||||
<source>Download files</source>
|
<source>Download files</source>
|
||||||
|
<target>‐Bestanden downloaden</target>
|
||||||
<note>alert action</note>
|
<note>alert action</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Downloaded" xml:space="preserve">
|
<trans-unit id="Downloaded" xml:space="preserve">
|
||||||
@@ -3026,7 +3078,7 @@ Dit is uw eigen eenmalige link!</target>
|
|||||||
<trans-unit id="Error switching profile!" xml:space="preserve">
|
<trans-unit id="Error switching profile!" xml:space="preserve">
|
||||||
<source>Error switching profile!</source>
|
<source>Error switching profile!</source>
|
||||||
<target>Fout bij wisselen van profiel!</target>
|
<target>Fout bij wisselen van profiel!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>alertTitle</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
||||||
<source>Error synchronizing connection</source>
|
<source>Error synchronizing connection</source>
|
||||||
@@ -3071,8 +3123,7 @@ Dit is uw eigen eenmalige link!</target>
|
|||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>Fout: %@</target>
|
<target>Fout: %@</target>
|
||||||
<note>file error text
|
<note>alert message</note>
|
||||||
snd error text</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
||||||
<source>Error: URL is invalid</source>
|
<source>Error: URL is invalid</source>
|
||||||
@@ -3162,6 +3213,8 @@ Dit is uw eigen eenmalige link!</target>
|
|||||||
<trans-unit id="File errors: %@" xml:space="preserve">
|
<trans-unit id="File errors: %@" xml:space="preserve">
|
||||||
<source>File errors:
|
<source>File errors:
|
||||||
%@</source>
|
%@</source>
|
||||||
|
<target>Bestandsfouten:
|
||||||
|
%@</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||||
@@ -3301,6 +3354,7 @@ Dit is uw eigen eenmalige link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
|
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
|
||||||
<source>Forward %d message(s)?</source>
|
<source>Forward %d message(s)?</source>
|
||||||
|
<target>%d bericht(en) doorsturen?</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward and save messages" xml:space="preserve">
|
<trans-unit id="Forward and save messages" xml:space="preserve">
|
||||||
@@ -3310,12 +3364,19 @@ Dit is uw eigen eenmalige link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward messages" xml:space="preserve">
|
<trans-unit id="Forward messages" xml:space="preserve">
|
||||||
<source>Forward messages</source>
|
<source>Forward messages</source>
|
||||||
|
<target>Berichten doorsturen</target>
|
||||||
<note>alert action</note>
|
<note>alert action</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward messages without files?" xml:space="preserve">
|
<trans-unit id="Forward messages without files?" xml:space="preserve">
|
||||||
<source>Forward messages without files?</source>
|
<source>Forward messages without files?</source>
|
||||||
|
<target>Berichten doorsturen zonder bestanden?</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Forward up to 20 messages at once." xml:space="preserve">
|
||||||
|
<source>Forward up to 20 messages at once.</source>
|
||||||
|
<target>Stuur maximaal 20 berichten tegelijk door.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Forwarded" xml:space="preserve">
|
<trans-unit id="Forwarded" xml:space="preserve">
|
||||||
<source>Forwarded</source>
|
<source>Forwarded</source>
|
||||||
<target>Doorgestuurd</target>
|
<target>Doorgestuurd</target>
|
||||||
@@ -3328,6 +3389,7 @@ Dit is uw eigen eenmalige link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
|
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
|
||||||
<source>Forwarding %lld messages</source>
|
<source>Forwarding %lld messages</source>
|
||||||
|
<target>%lld berichten doorsturen</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
|
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
|
||||||
@@ -3626,6 +3688,7 @@ Fout: %2$@</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="IP address" xml:space="preserve">
|
<trans-unit id="IP address" xml:space="preserve">
|
||||||
<source>IP address</source>
|
<source>IP address</source>
|
||||||
|
<target>IP-adres</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
|
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
|
||||||
@@ -3703,6 +3766,13 @@ Fout: %2$@</target>
|
|||||||
<target>Archief importeren</target>
|
<target>Archief importeren</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Improved delivery, reduced traffic usage. More improvements are coming soon!" xml:space="preserve">
|
||||||
|
<source>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</source>
|
||||||
|
<target>Verbeterde levering, minder data gebruik.
|
||||||
|
Binnenkort meer verbeteringen!</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Improved message delivery" xml:space="preserve">
|
<trans-unit id="Improved message delivery" xml:space="preserve">
|
||||||
<source>Improved message delivery</source>
|
<source>Improved message delivery</source>
|
||||||
<target>Verbeterde berichtbezorging</target>
|
<target>Verbeterde berichtbezorging</target>
|
||||||
@@ -4330,6 +4400,7 @@ Dit is jouw link voor groep %@!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
|
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
|
||||||
<source>Messages were deleted after you selected them.</source>
|
<source>Messages were deleted after you selected them.</source>
|
||||||
|
<target>Berichten zijn verwijderd nadat u ze had geselecteerd.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</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">
|
<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">
|
||||||
@@ -4487,6 +4558,16 @@ Dit is jouw link voor groep %@!</target>
|
|||||||
<target>Nieuwe toegangscode</target>
|
<target>Nieuwe toegangscode</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used every time you start the app." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used every time you start the app.</source>
|
||||||
|
<target>Elke keer dat u de app start, worden er nieuwe SOCKS-inloggegevens gebruikt.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used for each server." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used for each server.</source>
|
||||||
|
<target>Voor elke server worden nieuwe SOCKS-inloggegevens gebruikt.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="New chat" xml:space="preserve">
|
<trans-unit id="New chat" xml:space="preserve">
|
||||||
<source>New chat</source>
|
<source>New chat</source>
|
||||||
<target>Nieuw gesprek</target>
|
<target>Nieuw gesprek</target>
|
||||||
@@ -4607,6 +4688,16 @@ Dit is jouw link voor groep %@!</target>
|
|||||||
<target>Geen netwerkverbinding</target>
|
<target>Geen netwerkverbinding</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record speech" xml:space="preserve">
|
||||||
|
<source>No permission to record speech</source>
|
||||||
|
<target>Geen toestemming om spraak op te nemen</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record video" xml:space="preserve">
|
||||||
|
<source>No permission to record video</source>
|
||||||
|
<target>Geen toestemming om video op te nemen</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
||||||
<source>No permission to record voice message</source>
|
<source>No permission to record voice message</source>
|
||||||
<target>Geen toestemming om spraakbericht op te nemen</target>
|
<target>Geen toestemming om spraakbericht op te nemen</target>
|
||||||
@@ -4629,6 +4720,7 @@ Dit is jouw link voor groep %@!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Nothing to forward!" xml:space="preserve">
|
<trans-unit id="Nothing to forward!" xml:space="preserve">
|
||||||
<source>Nothing to forward!</source>
|
<source>Nothing to forward!</source>
|
||||||
|
<target>Niets om door te sturen!</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Notifications" xml:space="preserve">
|
<trans-unit id="Notifications" xml:space="preserve">
|
||||||
@@ -4857,6 +4949,8 @@ Vereist het inschakelen van VPN.</target>
|
|||||||
<trans-unit id="Other file errors: %@" xml:space="preserve">
|
<trans-unit id="Other file errors: %@" xml:space="preserve">
|
||||||
<source>Other file errors:
|
<source>Other file errors:
|
||||||
%@</source>
|
%@</source>
|
||||||
|
<target>Andere bestandsfouten:
|
||||||
|
%@</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="PING count" xml:space="preserve">
|
<trans-unit id="PING count" xml:space="preserve">
|
||||||
@@ -4896,6 +4990,7 @@ Vereist het inschakelen van VPN.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Password" xml:space="preserve">
|
<trans-unit id="Password" xml:space="preserve">
|
||||||
<source>Password</source>
|
<source>Password</source>
|
||||||
|
<target>Wachtwoord</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Password to show" xml:space="preserve">
|
<trans-unit id="Password to show" xml:space="preserve">
|
||||||
@@ -5049,6 +5144,7 @@ Fout: %@</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Port" xml:space="preserve">
|
<trans-unit id="Port" xml:space="preserve">
|
||||||
<source>Port</source>
|
<source>Port</source>
|
||||||
|
<target>Poort</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
|
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
|
||||||
@@ -5240,6 +5336,7 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Proxy requires password" xml:space="preserve">
|
<trans-unit id="Proxy requires password" xml:space="preserve">
|
||||||
<source>Proxy requires password</source>
|
<source>Proxy requires password</source>
|
||||||
|
<target>Proxy vereist wachtwoord</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Push notifications" xml:space="preserve">
|
<trans-unit id="Push notifications" xml:space="preserve">
|
||||||
@@ -5650,6 +5747,7 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="SOCKS proxy" xml:space="preserve">
|
<trans-unit id="SOCKS proxy" xml:space="preserve">
|
||||||
<source>SOCKS proxy</source>
|
<source>SOCKS proxy</source>
|
||||||
|
<target>SOCKS proxy</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Safely receive files" xml:space="preserve">
|
<trans-unit id="Safely receive files" xml:space="preserve">
|
||||||
@@ -5765,6 +5863,7 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Saving %lld messages" xml:space="preserve">
|
<trans-unit id="Saving %lld messages" xml:space="preserve">
|
||||||
<source>Saving %lld messages</source>
|
<source>Saving %lld messages</source>
|
||||||
|
<target>%lld berichten opslaan</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Scale" xml:space="preserve">
|
<trans-unit id="Scale" xml:space="preserve">
|
||||||
@@ -6067,6 +6166,11 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
|
|||||||
<target>Verzonden via proxy</target>
|
<target>Verzonden via proxy</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<target>Server</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Server address" xml:space="preserve">
|
<trans-unit id="Server address" xml:space="preserve">
|
||||||
<source>Server address</source>
|
<source>Server address</source>
|
||||||
<target>Server adres</target>
|
<target>Server adres</target>
|
||||||
@@ -6367,6 +6471,11 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
|
|||||||
<target>Eenmalige SimpleX uitnodiging</target>
|
<target>Eenmalige SimpleX uitnodiging</target>
|
||||||
<note>simplex link type</note>
|
<note>simplex link type</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SimpleX protocols reviewed by Trail of Bits." xml:space="preserve">
|
||||||
|
<source>SimpleX protocols reviewed by Trail of Bits.</source>
|
||||||
|
<target>SimpleX-protocollen beoordeeld door Trail of Bits.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
||||||
<source>Simplified incognito mode</source>
|
<source>Simplified incognito mode</source>
|
||||||
<target>Vereenvoudigde incognitomodus</target>
|
<target>Vereenvoudigde incognitomodus</target>
|
||||||
@@ -6524,17 +6633,17 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Subscribed" xml:space="preserve">
|
<trans-unit id="Subscribed" xml:space="preserve">
|
||||||
<source>Subscribed</source>
|
<source>Subscribed</source>
|
||||||
<target>Ingeschreven</target>
|
<target>Subscribed</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Subscription errors" xml:space="preserve">
|
<trans-unit id="Subscription errors" xml:space="preserve">
|
||||||
<source>Subscription errors</source>
|
<source>Subscription errors</source>
|
||||||
<target>Inschrijving fouten</target>
|
<target>Subscription fouten</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Subscriptions ignored" xml:space="preserve">
|
<trans-unit id="Subscriptions ignored" xml:space="preserve">
|
||||||
<source>Subscriptions ignored</source>
|
<source>Subscriptions ignored</source>
|
||||||
<target>Inschrijvingen genegeerd</target>
|
<target>Subscriptions genegeerd</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Support SimpleX Chat" xml:space="preserve">
|
<trans-unit id="Support SimpleX Chat" xml:space="preserve">
|
||||||
@@ -6542,6 +6651,16 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
|
|||||||
<target>Ondersteuning van SimpleX Chat</target>
|
<target>Ondersteuning van SimpleX Chat</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch audio and video during the call." xml:space="preserve">
|
||||||
|
<source>Switch audio and video during the call.</source>
|
||||||
|
<target>Wisselen tussen audio en video tijdens het gesprek.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch chat profile for 1-time invitations." xml:space="preserve">
|
||||||
|
<source>Switch chat profile for 1-time invitations.</source>
|
||||||
|
<target>Wijzig chatprofiel voor eenmalige uitnodigingen.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="System" xml:space="preserve">
|
<trans-unit id="System" xml:space="preserve">
|
||||||
<source>System</source>
|
<source>System</source>
|
||||||
<target>Systeem</target>
|
<target>Systeem</target>
|
||||||
@@ -6579,6 +6698,7 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Tail" xml:space="preserve">
|
<trans-unit id="Tail" xml:space="preserve">
|
||||||
<source>Tail</source>
|
<source>Tail</source>
|
||||||
|
<target>Staart</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Take picture" xml:space="preserve">
|
<trans-unit id="Take picture" xml:space="preserve">
|
||||||
@@ -6905,6 +7025,16 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||||||
U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingeschakeld.</target>
|
U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingeschakeld.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="To record speech please grant permission to use Microphone." xml:space="preserve">
|
||||||
|
<source>To record speech please grant permission to use Microphone.</source>
|
||||||
|
<target>Geef toestemming om de microfoon te gebruiken om spraak op te nemen.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="To record video please grant permission to use Camera." xml:space="preserve">
|
||||||
|
<source>To record video please grant permission to use Camera.</source>
|
||||||
|
<target>Om video op te nemen, dient u toestemming te geven om de camera te gebruiken.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
||||||
<source>To record voice message please grant permission to use Microphone.</source>
|
<source>To record voice message please grant permission to use Microphone.</source>
|
||||||
<target>Geef toestemming om de microfoon te gebruiken om een spraakbericht op te nemen.</target>
|
<target>Geef toestemming om de microfoon te gebruiken om een spraakbericht op te nemen.</target>
|
||||||
@@ -7174,6 +7304,7 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
|
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
|
||||||
<source>Use SOCKS proxy</source>
|
<source>Use SOCKS proxy</source>
|
||||||
|
<target>Gebruik SOCKS proxy</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
|
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
|
||||||
@@ -7241,11 +7372,6 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
|
|||||||
<target>Gebruik de app met één hand.</target>
|
<target>Gebruik de app met één hand.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User profile" xml:space="preserve">
|
|
||||||
<source>User profile</source>
|
|
||||||
<target>Gebruikers profiel</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User selection" xml:space="preserve">
|
<trans-unit id="User selection" xml:space="preserve">
|
||||||
<source>User selection</source>
|
<source>User selection</source>
|
||||||
<target>Gebruikersselectie</target>
|
<target>Gebruikersselectie</target>
|
||||||
@@ -7253,6 +7379,7 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Username" xml:space="preserve">
|
<trans-unit id="Username" xml:space="preserve">
|
||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
|
<target>Gebruikersnaam</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
|
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
|
||||||
@@ -7515,11 +7642,6 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
|
|||||||
<target>XFTP server</target>
|
<target>XFTP server</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="You" xml:space="preserve">
|
|
||||||
<source>You</source>
|
|
||||||
<target>Jij</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">
|
<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>
|
<source>You **must not** use the same database on two devices.</source>
|
||||||
<target>U **mag** niet dezelfde database op twee apparaten gebruiken.</target>
|
<target>U **mag** niet dezelfde database op twee apparaten gebruiken.</target>
|
||||||
@@ -7901,6 +8023,7 @@ Verbindingsverzoek herhalen?</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
|
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
|
||||||
<source>Your credentials may be sent unencrypted.</source>
|
<source>Your credentials may be sent unencrypted.</source>
|
||||||
|
<target>Uw inloggegevens worden mogelijk niet-versleuteld verzonden.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
|
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
|
||||||
@@ -8881,7 +9004,7 @@ laatst ontvangen bericht: %2$@</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="you are observer" xml:space="preserve">
|
<trans-unit id="you are observer" xml:space="preserve">
|
||||||
<source>you are observer</source>
|
<source>you are observer</source>
|
||||||
<target>jij bent waarnemer</target>
|
<target>je bent waarnemer</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="you blocked %@" xml:space="preserve">
|
<trans-unit id="you blocked %@" xml:space="preserve">
|
||||||
@@ -8911,7 +9034,7 @@ laatst ontvangen bericht: %2$@</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="you left" xml:space="preserve">
|
<trans-unit id="you left" xml:space="preserve">
|
||||||
<source>you left</source>
|
<source>you left</source>
|
||||||
<target>jij bent vertrokken</target>
|
<target>je bent vertrokken</target>
|
||||||
<note>snd group event chat item</note>
|
<note>snd group event chat item</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="you removed %@" xml:space="preserve">
|
<trans-unit id="you removed %@" xml:space="preserve">
|
||||||
|
|||||||
@@ -139,6 +139,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%@, %@" xml:space="preserve">
|
<trans-unit id="%@, %@" xml:space="preserve">
|
||||||
<source>%1$@, %2$@</source>
|
<source>%1$@, %2$@</source>
|
||||||
|
<target>%1$@, %2$@</target>
|
||||||
<note>format for date separator in chat</note>
|
<note>format for date separator in chat</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%@, %@ and %lld members" xml:space="preserve">
|
<trans-unit id="%@, %@ and %lld members" xml:space="preserve">
|
||||||
@@ -163,18 +164,22 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
|
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
|
||||||
<source>%d file(s) are still being downloaded.</source>
|
<source>%d file(s) are still being downloaded.</source>
|
||||||
|
<target>%d plik(ów) jest dalej pobieranych.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
|
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
|
||||||
<source>%d file(s) failed to download.</source>
|
<source>%d file(s) failed to download.</source>
|
||||||
|
<target>%d plik(ów) nie udało się pobrać.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
|
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
|
||||||
<source>%d file(s) were deleted.</source>
|
<source>%d file(s) were deleted.</source>
|
||||||
|
<target>%d plik(ów) zostało usuniętych.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
|
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
|
||||||
<source>%d file(s) were not downloaded.</source>
|
<source>%d file(s) were not downloaded.</source>
|
||||||
|
<target>%d plik(ów) nie zostało pobranych.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d hours" xml:space="preserve">
|
<trans-unit id="%d hours" xml:space="preserve">
|
||||||
@@ -184,6 +189,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d messages not forwarded" xml:space="preserve">
|
<trans-unit id="%d messages not forwarded" xml:space="preserve">
|
||||||
<source>%d messages not forwarded</source>
|
<source>%d messages not forwarded</source>
|
||||||
|
<target>%d wiadomości nie przekazanych</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d min" xml:space="preserve">
|
<trans-unit id="%d min" xml:space="preserve">
|
||||||
@@ -747,7 +753,7 @@
|
|||||||
<trans-unit id="All profiles" xml:space="preserve">
|
<trans-unit id="All profiles" xml:space="preserve">
|
||||||
<source>All profiles</source>
|
<source>All profiles</source>
|
||||||
<target>Wszystkie profile</target>
|
<target>Wszystkie profile</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>profile dropdown</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||||
<source>All your contacts will remain connected.</source>
|
<source>All your contacts will remain connected.</source>
|
||||||
@@ -939,6 +945,11 @@
|
|||||||
<target>Pin aplikacji został zastąpiony pinem samozniszczenia.</target>
|
<target>Pin aplikacji został zastąpiony pinem samozniszczenia.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="App session" xml:space="preserve">
|
||||||
|
<source>App session</source>
|
||||||
|
<target>Sesja aplikacji</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="App version" xml:space="preserve">
|
<trans-unit id="App version" xml:space="preserve">
|
||||||
<source>App version</source>
|
<source>App version</source>
|
||||||
<target>Wersja aplikacji</target>
|
<target>Wersja aplikacji</target>
|
||||||
@@ -1046,6 +1057,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Auto-accept settings" xml:space="preserve">
|
<trans-unit id="Auto-accept settings" xml:space="preserve">
|
||||||
<source>Auto-accept settings</source>
|
<source>Auto-accept settings</source>
|
||||||
|
<target>Ustawienia automatycznej akceptacji</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Back" xml:space="preserve">
|
<trans-unit id="Back" xml:space="preserve">
|
||||||
@@ -1073,11 +1085,19 @@
|
|||||||
<target>Zły hash wiadomości</target>
|
<target>Zły hash wiadomości</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better calls" xml:space="preserve">
|
||||||
|
<source>Better calls</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better groups" xml:space="preserve">
|
<trans-unit id="Better groups" xml:space="preserve">
|
||||||
<source>Better groups</source>
|
<source>Better groups</source>
|
||||||
<target>Lepsze grupy</target>
|
<target>Lepsze grupy</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better message dates." xml:space="preserve">
|
||||||
|
<source>Better message dates.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better messages" xml:space="preserve">
|
<trans-unit id="Better messages" xml:space="preserve">
|
||||||
<source>Better messages</source>
|
<source>Better messages</source>
|
||||||
<target>Lepsze wiadomości</target>
|
<target>Lepsze wiadomości</target>
|
||||||
@@ -1088,6 +1108,18 @@
|
|||||||
<target>Lepsze sieciowanie</target>
|
<target>Lepsze sieciowanie</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better notifications" xml:space="preserve">
|
||||||
|
<source>Better notifications</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||||
|
<source>Better security ✅</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better user experience" xml:space="preserve">
|
||||||
|
<source>Better user experience</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Black" xml:space="preserve">
|
<trans-unit id="Black" xml:space="preserve">
|
||||||
<source>Black</source>
|
<source>Black</source>
|
||||||
<target>Czarny</target>
|
<target>Czarny</target>
|
||||||
@@ -1371,8 +1403,14 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Chat preferences were changed." xml:space="preserve">
|
<trans-unit id="Chat preferences were changed." xml:space="preserve">
|
||||||
<source>Chat preferences were changed.</source>
|
<source>Chat preferences were changed.</source>
|
||||||
|
<target>Preferencje czatu zostały zmienione.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat profile" xml:space="preserve">
|
||||||
|
<source>Chat profile</source>
|
||||||
|
<target>Profil użytkownika</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Chat theme" xml:space="preserve">
|
<trans-unit id="Chat theme" xml:space="preserve">
|
||||||
<source>Chat theme</source>
|
<source>Chat theme</source>
|
||||||
<target>Motyw czatu</target>
|
<target>Motyw czatu</target>
|
||||||
@@ -1774,6 +1812,7 @@ To jest twój jednorazowy link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Corner" xml:space="preserve">
|
<trans-unit id="Corner" xml:space="preserve">
|
||||||
<source>Corner</source>
|
<source>Corner</source>
|
||||||
|
<target>Róg</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Correct name to %@?" xml:space="preserve">
|
<trans-unit id="Correct name to %@?" xml:space="preserve">
|
||||||
@@ -1901,6 +1940,10 @@ To jest twój jednorazowy link!</target>
|
|||||||
<target>Niestandardowy czas</target>
|
<target>Niestandardowy czas</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Customizable message shape." xml:space="preserve">
|
||||||
|
<source>Customizable message shape.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Customize theme" xml:space="preserve">
|
<trans-unit id="Customize theme" xml:space="preserve">
|
||||||
<source>Customize theme</source>
|
<source>Customize theme</source>
|
||||||
<target>Dostosuj motyw</target>
|
<target>Dostosuj motyw</target>
|
||||||
@@ -2195,6 +2238,10 @@ To jest twój jednorazowy link!</target>
|
|||||||
<target>Usunąć starą bazę danych?</target>
|
<target>Usunąć starą bazę danych?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Delete or moderate up to 200 messages." xml:space="preserve">
|
||||||
|
<source>Delete or moderate up to 200 messages.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
||||||
<source>Delete pending connection?</source>
|
<source>Delete pending connection?</source>
|
||||||
<target>Usunąć oczekujące połączenie?</target>
|
<target>Usunąć oczekujące połączenie?</target>
|
||||||
@@ -2447,6 +2494,7 @@ To jest twój jednorazowy link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
|
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
|
||||||
<source>Do not use credentials with proxy.</source>
|
<source>Do not use credentials with proxy.</source>
|
||||||
|
<target>Nie używaj danych logowania do proxy.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Don't create address" xml:space="preserve">
|
<trans-unit id="Don't create address" xml:space="preserve">
|
||||||
@@ -2492,6 +2540,7 @@ To jest twój jednorazowy link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Download files" xml:space="preserve">
|
<trans-unit id="Download files" xml:space="preserve">
|
||||||
<source>Download files</source>
|
<source>Download files</source>
|
||||||
|
<target>Pobierz pliki</target>
|
||||||
<note>alert action</note>
|
<note>alert action</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Downloaded" xml:space="preserve">
|
<trans-unit id="Downloaded" xml:space="preserve">
|
||||||
@@ -2771,6 +2820,7 @@ To jest twój jednorazowy link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error changing connection profile" xml:space="preserve">
|
<trans-unit id="Error changing connection profile" xml:space="preserve">
|
||||||
<source>Error changing connection profile</source>
|
<source>Error changing connection profile</source>
|
||||||
|
<target>Błąd zmiany połączenia profilu</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error changing role" xml:space="preserve">
|
<trans-unit id="Error changing role" xml:space="preserve">
|
||||||
@@ -2785,6 +2835,7 @@ To jest twój jednorazowy link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error changing to incognito!" xml:space="preserve">
|
<trans-unit id="Error changing to incognito!" xml:space="preserve">
|
||||||
<source>Error changing to incognito!</source>
|
<source>Error changing to incognito!</source>
|
||||||
|
<target>Błąd zmiany na incognito!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
||||||
@@ -2909,6 +2960,7 @@ To jest twój jednorazowy link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error migrating settings" xml:space="preserve">
|
<trans-unit id="Error migrating settings" xml:space="preserve">
|
||||||
<source>Error migrating settings</source>
|
<source>Error migrating settings</source>
|
||||||
|
<target>Błąd migracji ustawień</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error opening chat" xml:space="preserve">
|
<trans-unit id="Error opening chat" xml:space="preserve">
|
||||||
@@ -3013,12 +3065,13 @@ To jest twój jednorazowy link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error switching profile" xml:space="preserve">
|
<trans-unit id="Error switching profile" xml:space="preserve">
|
||||||
<source>Error switching profile</source>
|
<source>Error switching profile</source>
|
||||||
|
<target>Błąd zmiany profilu</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error switching profile!" xml:space="preserve">
|
<trans-unit id="Error switching profile!" xml:space="preserve">
|
||||||
<source>Error switching profile!</source>
|
<source>Error switching profile!</source>
|
||||||
<target>Błąd przełączania profilu!</target>
|
<target>Błąd przełączania profilu!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>alertTitle</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
||||||
<source>Error synchronizing connection</source>
|
<source>Error synchronizing connection</source>
|
||||||
@@ -3063,8 +3116,7 @@ To jest twój jednorazowy link!</target>
|
|||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>Błąd: %@</target>
|
<target>Błąd: %@</target>
|
||||||
<note>file error text
|
<note>alert message</note>
|
||||||
snd error text</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
||||||
<source>Error: URL is invalid</source>
|
<source>Error: URL is invalid</source>
|
||||||
@@ -3154,6 +3206,8 @@ To jest twój jednorazowy link!</target>
|
|||||||
<trans-unit id="File errors: %@" xml:space="preserve">
|
<trans-unit id="File errors: %@" xml:space="preserve">
|
||||||
<source>File errors:
|
<source>File errors:
|
||||||
%@</source>
|
%@</source>
|
||||||
|
<target>Błędy pliku:
|
||||||
|
%@</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||||
@@ -3293,6 +3347,7 @@ To jest twój jednorazowy link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
|
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
|
||||||
<source>Forward %d message(s)?</source>
|
<source>Forward %d message(s)?</source>
|
||||||
|
<target>Przekazać %d wiadomość(i)?</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward and save messages" xml:space="preserve">
|
<trans-unit id="Forward and save messages" xml:space="preserve">
|
||||||
@@ -3302,12 +3357,18 @@ To jest twój jednorazowy link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward messages" xml:space="preserve">
|
<trans-unit id="Forward messages" xml:space="preserve">
|
||||||
<source>Forward messages</source>
|
<source>Forward messages</source>
|
||||||
|
<target>Przekaż wiadomości</target>
|
||||||
<note>alert action</note>
|
<note>alert action</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward messages without files?" xml:space="preserve">
|
<trans-unit id="Forward messages without files?" xml:space="preserve">
|
||||||
<source>Forward messages without files?</source>
|
<source>Forward messages without files?</source>
|
||||||
|
<target>Przekazać wiadomości bez plików?</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Forward up to 20 messages at once." xml:space="preserve">
|
||||||
|
<source>Forward up to 20 messages at once.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Forwarded" xml:space="preserve">
|
<trans-unit id="Forwarded" xml:space="preserve">
|
||||||
<source>Forwarded</source>
|
<source>Forwarded</source>
|
||||||
<target>Przekazane dalej</target>
|
<target>Przekazane dalej</target>
|
||||||
@@ -3320,6 +3381,7 @@ To jest twój jednorazowy link!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
|
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
|
||||||
<source>Forwarding %lld messages</source>
|
<source>Forwarding %lld messages</source>
|
||||||
|
<target>Przekazywanie %lld wiadomości</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
|
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
|
||||||
@@ -3618,6 +3680,7 @@ Błąd: %2$@</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="IP address" xml:space="preserve">
|
<trans-unit id="IP address" xml:space="preserve">
|
||||||
<source>IP address</source>
|
<source>IP address</source>
|
||||||
|
<target>Adres IP</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
|
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
|
||||||
@@ -3695,6 +3758,11 @@ Błąd: %2$@</target>
|
|||||||
<target>Importowanie archiwum</target>
|
<target>Importowanie archiwum</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Improved delivery, reduced traffic usage. More improvements are coming soon!" xml:space="preserve">
|
||||||
|
<source>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Improved message delivery" xml:space="preserve">
|
<trans-unit id="Improved message delivery" xml:space="preserve">
|
||||||
<source>Improved message delivery</source>
|
<source>Improved message delivery</source>
|
||||||
<target>Ulepszona dostawa wiadomości</target>
|
<target>Ulepszona dostawa wiadomości</target>
|
||||||
@@ -4267,6 +4335,7 @@ To jest twój link do grupy %@!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Message shape" xml:space="preserve">
|
<trans-unit id="Message shape" xml:space="preserve">
|
||||||
<source>Message shape</source>
|
<source>Message shape</source>
|
||||||
|
<target>Kształt wiadomości</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Message source remains private." xml:space="preserve">
|
<trans-unit id="Message source remains private." xml:space="preserve">
|
||||||
@@ -4321,6 +4390,7 @@ To jest twój link do grupy %@!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
|
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
|
||||||
<source>Messages were deleted after you selected them.</source>
|
<source>Messages were deleted after you selected them.</source>
|
||||||
|
<target>Wiadomości zostały usunięte po wybraniu ich.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</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">
|
<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">
|
||||||
@@ -4478,6 +4548,16 @@ To jest twój link do grupy %@!</target>
|
|||||||
<target>Nowy Pin</target>
|
<target>Nowy Pin</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used every time you start the app." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used every time you start the app.</source>
|
||||||
|
<target>Nowe poświadczenia SOCKS będą używane przy każdym uruchomieniu aplikacji.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used for each server." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used for each server.</source>
|
||||||
|
<target>Dla każdego serwera zostaną użyte nowe poświadczenia SOCKS.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="New chat" xml:space="preserve">
|
<trans-unit id="New chat" xml:space="preserve">
|
||||||
<source>New chat</source>
|
<source>New chat</source>
|
||||||
<target>Nowy czat</target>
|
<target>Nowy czat</target>
|
||||||
@@ -4598,6 +4678,16 @@ To jest twój link do grupy %@!</target>
|
|||||||
<target>Brak połączenia z siecią</target>
|
<target>Brak połączenia z siecią</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record speech" xml:space="preserve">
|
||||||
|
<source>No permission to record speech</source>
|
||||||
|
<target>Brak zezwoleń do nagrania rozmowy</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record video" xml:space="preserve">
|
||||||
|
<source>No permission to record video</source>
|
||||||
|
<target>Brak zezwoleń do nagrania wideo</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
||||||
<source>No permission to record voice message</source>
|
<source>No permission to record voice message</source>
|
||||||
<target>Brak uprawnień do nagrywania wiadomości głosowej</target>
|
<target>Brak uprawnień do nagrywania wiadomości głosowej</target>
|
||||||
@@ -4620,6 +4710,7 @@ To jest twój link do grupy %@!</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Nothing to forward!" xml:space="preserve">
|
<trans-unit id="Nothing to forward!" xml:space="preserve">
|
||||||
<source>Nothing to forward!</source>
|
<source>Nothing to forward!</source>
|
||||||
|
<target>Nic do przekazania!</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Notifications" xml:space="preserve">
|
<trans-unit id="Notifications" xml:space="preserve">
|
||||||
@@ -4848,6 +4939,8 @@ Wymaga włączenia VPN.</target>
|
|||||||
<trans-unit id="Other file errors: %@" xml:space="preserve">
|
<trans-unit id="Other file errors: %@" xml:space="preserve">
|
||||||
<source>Other file errors:
|
<source>Other file errors:
|
||||||
%@</source>
|
%@</source>
|
||||||
|
<target>Inne błędy pliku:
|
||||||
|
%@</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="PING count" xml:space="preserve">
|
<trans-unit id="PING count" xml:space="preserve">
|
||||||
@@ -4887,6 +4980,7 @@ Wymaga włączenia VPN.</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Password" xml:space="preserve">
|
<trans-unit id="Password" xml:space="preserve">
|
||||||
<source>Password</source>
|
<source>Password</source>
|
||||||
|
<target>Hasło</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Password to show" xml:space="preserve">
|
<trans-unit id="Password to show" xml:space="preserve">
|
||||||
@@ -5040,6 +5134,7 @@ Błąd: %@</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Port" xml:space="preserve">
|
<trans-unit id="Port" xml:space="preserve">
|
||||||
<source>Port</source>
|
<source>Port</source>
|
||||||
|
<target>Port</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
|
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
|
||||||
@@ -5231,6 +5326,7 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Proxy requires password" xml:space="preserve">
|
<trans-unit id="Proxy requires password" xml:space="preserve">
|
||||||
<source>Proxy requires password</source>
|
<source>Proxy requires password</source>
|
||||||
|
<target>Proxy wymaga hasła</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Push notifications" xml:space="preserve">
|
<trans-unit id="Push notifications" xml:space="preserve">
|
||||||
@@ -5456,6 +5552,7 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Remove archive?" xml:space="preserve">
|
<trans-unit id="Remove archive?" xml:space="preserve">
|
||||||
<source>Remove archive?</source>
|
<source>Remove archive?</source>
|
||||||
|
<target>Usunąć archiwum?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Remove image" xml:space="preserve">
|
<trans-unit id="Remove image" xml:space="preserve">
|
||||||
@@ -5640,6 +5737,7 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="SOCKS proxy" xml:space="preserve">
|
<trans-unit id="SOCKS proxy" xml:space="preserve">
|
||||||
<source>SOCKS proxy</source>
|
<source>SOCKS proxy</source>
|
||||||
|
<target>Proxy SOCKS</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Safely receive files" xml:space="preserve">
|
<trans-unit id="Safely receive files" xml:space="preserve">
|
||||||
@@ -5730,6 +5828,7 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Save your profile?" xml:space="preserve">
|
<trans-unit id="Save your profile?" xml:space="preserve">
|
||||||
<source>Save your profile?</source>
|
<source>Save your profile?</source>
|
||||||
|
<target>Zapisać Twój profil?</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Saved" xml:space="preserve">
|
<trans-unit id="Saved" xml:space="preserve">
|
||||||
@@ -5754,6 +5853,7 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Saving %lld messages" xml:space="preserve">
|
<trans-unit id="Saving %lld messages" xml:space="preserve">
|
||||||
<source>Saving %lld messages</source>
|
<source>Saving %lld messages</source>
|
||||||
|
<target>Zapisywanie %lld wiadomości</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Scale" xml:space="preserve">
|
<trans-unit id="Scale" xml:space="preserve">
|
||||||
@@ -5838,6 +5938,7 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Select chat profile" xml:space="preserve">
|
<trans-unit id="Select chat profile" xml:space="preserve">
|
||||||
<source>Select chat profile</source>
|
<source>Select chat profile</source>
|
||||||
|
<target>Wybierz profil czatu</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Selected %lld" xml:space="preserve">
|
<trans-unit id="Selected %lld" xml:space="preserve">
|
||||||
@@ -6055,6 +6156,11 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||||||
<target>Wysłano przez proxy</target>
|
<target>Wysłano przez proxy</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<target>Serwer</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Server address" xml:space="preserve">
|
<trans-unit id="Server address" xml:space="preserve">
|
||||||
<source>Server address</source>
|
<source>Server address</source>
|
||||||
<target>Adres serwera</target>
|
<target>Adres serwera</target>
|
||||||
@@ -6177,6 +6283,7 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Settings were changed." xml:space="preserve">
|
<trans-unit id="Settings were changed." xml:space="preserve">
|
||||||
<source>Settings were changed.</source>
|
<source>Settings were changed.</source>
|
||||||
|
<target>Ustawienia zostały zmienione.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Shape profile images" xml:space="preserve">
|
<trans-unit id="Shape profile images" xml:space="preserve">
|
||||||
@@ -6216,6 +6323,7 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Share profile" xml:space="preserve">
|
<trans-unit id="Share profile" xml:space="preserve">
|
||||||
<source>Share profile</source>
|
<source>Share profile</source>
|
||||||
|
<target>Udostępnij profil</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Share this 1-time invite link" xml:space="preserve">
|
<trans-unit id="Share this 1-time invite link" xml:space="preserve">
|
||||||
@@ -6353,6 +6461,10 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||||||
<target>Zaproszenie jednorazowe SimpleX</target>
|
<target>Zaproszenie jednorazowe SimpleX</target>
|
||||||
<note>simplex link type</note>
|
<note>simplex link type</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SimpleX protocols reviewed by Trail of Bits." xml:space="preserve">
|
||||||
|
<source>SimpleX protocols reviewed by Trail of Bits.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
||||||
<source>Simplified incognito mode</source>
|
<source>Simplified incognito mode</source>
|
||||||
<target>Uproszczony tryb incognito</target>
|
<target>Uproszczony tryb incognito</target>
|
||||||
@@ -6385,6 +6497,7 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
|
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
|
||||||
<source>Some app settings were not migrated.</source>
|
<source>Some app settings were not migrated.</source>
|
||||||
|
<target>Niektóre ustawienia aplikacji nie zostały zmigrowane.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
|
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
|
||||||
@@ -6527,6 +6640,14 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||||||
<target>Wspieraj SimpleX Chat</target>
|
<target>Wspieraj SimpleX Chat</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch audio and video during the call." xml:space="preserve">
|
||||||
|
<source>Switch audio and video during the call.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch chat profile for 1-time invitations." xml:space="preserve">
|
||||||
|
<source>Switch chat profile for 1-time invitations.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="System" xml:space="preserve">
|
<trans-unit id="System" xml:space="preserve">
|
||||||
<source>System</source>
|
<source>System</source>
|
||||||
<target>System</target>
|
<target>System</target>
|
||||||
@@ -6564,6 +6685,7 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Tail" xml:space="preserve">
|
<trans-unit id="Tail" xml:space="preserve">
|
||||||
<source>Tail</source>
|
<source>Tail</source>
|
||||||
|
<target>Ogon</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Take picture" xml:space="preserve">
|
<trans-unit id="Take picture" xml:space="preserve">
|
||||||
@@ -6760,6 +6882,7 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
|
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
|
||||||
<source>The uploaded database archive will be permanently removed from the servers.</source>
|
<source>The uploaded database archive will be permanently removed from the servers.</source>
|
||||||
|
<target>Przesłane archiwum bazy danych zostanie trwale usunięte z serwerów.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Themes" xml:space="preserve">
|
<trans-unit id="Themes" xml:space="preserve">
|
||||||
@@ -6889,6 +7012,16 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||||||
Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.</target>
|
Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="To record speech please grant permission to use Microphone." xml:space="preserve">
|
||||||
|
<source>To record speech please grant permission to use Microphone.</source>
|
||||||
|
<target>Aby nagrać rozmowę, proszę zezwolić na użycie Mikrofonu.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="To record video please grant permission to use Camera." xml:space="preserve">
|
||||||
|
<source>To record video please grant permission to use Camera.</source>
|
||||||
|
<target>Aby nagrać wideo, proszę zezwolić na użycie Aparatu.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
||||||
<source>To record voice message please grant permission to use Microphone.</source>
|
<source>To record voice message please grant permission to use Microphone.</source>
|
||||||
<target>Aby nagrać wiadomość głosową należy udzielić zgody na użycie Mikrofonu.</target>
|
<target>Aby nagrać wiadomość głosową należy udzielić zgody na użycie Mikrofonu.</target>
|
||||||
@@ -7158,6 +7291,7 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
|
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
|
||||||
<source>Use SOCKS proxy</source>
|
<source>Use SOCKS proxy</source>
|
||||||
|
<target>Użyj proxy SOCKS</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
|
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
|
||||||
@@ -7225,11 +7359,6 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
|
|||||||
<target>Korzystaj z aplikacji jedną ręką.</target>
|
<target>Korzystaj z aplikacji jedną ręką.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User profile" xml:space="preserve">
|
|
||||||
<source>User profile</source>
|
|
||||||
<target>Profil użytkownika</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User selection" xml:space="preserve">
|
<trans-unit id="User selection" xml:space="preserve">
|
||||||
<source>User selection</source>
|
<source>User selection</source>
|
||||||
<target>Wybór użytkownika</target>
|
<target>Wybór użytkownika</target>
|
||||||
@@ -7237,6 +7366,7 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Username" xml:space="preserve">
|
<trans-unit id="Username" xml:space="preserve">
|
||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
|
<target>Nazwa użytkownika</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
|
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
|
||||||
@@ -7499,11 +7629,6 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
|
|||||||
<target>Serwer XFTP</target>
|
<target>Serwer XFTP</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="You" xml:space="preserve">
|
|
||||||
<source>You</source>
|
|
||||||
<target>Ty</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">
|
<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>
|
<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>
|
<target>**Nie możesz** używać tej samej bazy na dwóch urządzeniach.</target>
|
||||||
@@ -7855,6 +7980,7 @@ Powtórzyć prośbę połączenia?</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your chat preferences" xml:space="preserve">
|
<trans-unit id="Your chat preferences" xml:space="preserve">
|
||||||
<source>Your chat preferences</source>
|
<source>Your chat preferences</source>
|
||||||
|
<target>Twoje preferencje czatu</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your chat profiles" xml:space="preserve">
|
<trans-unit id="Your chat profiles" xml:space="preserve">
|
||||||
@@ -7864,6 +7990,7 @@ Powtórzyć prośbę połączenia?</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile." xml:space="preserve">
|
<trans-unit id="Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile." xml:space="preserve">
|
||||||
<source>Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile.</source>
|
<source>Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile.</source>
|
||||||
|
<target>Twoje połączenie zostało przeniesione do %@, ale podczas przekierowywania do profilu wystąpił nieoczekiwany błąd.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your contact sent a file that is larger than currently supported maximum size (%@)." xml:space="preserve">
|
<trans-unit id="Your contact sent a file that is larger than currently supported maximum size (%@)." xml:space="preserve">
|
||||||
@@ -7883,6 +8010,7 @@ Powtórzyć prośbę połączenia?</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
|
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
|
||||||
<source>Your credentials may be sent unencrypted.</source>
|
<source>Your credentials may be sent unencrypted.</source>
|
||||||
|
<target>Twoje poświadczenia mogą zostać wysłane niezaszyfrowane.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
|
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
|
||||||
@@ -7922,6 +8050,7 @@ Powtórzyć prośbę połączenia?</target>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
|
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
|
||||||
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
|
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
|
||||||
|
<target>Twój profil został zmieniony. Jeśli go zapiszesz, zaktualizowany profil zostanie wysłany do wszystkich kontaktów.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
|
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
|
||||||
|
|||||||
@@ -5502,6 +5502,74 @@ Isso pode acontecer por causa de algum bug ou quando a conexão está comprometi
|
|||||||
<source>Archived contacts</source>
|
<source>Archived contacts</source>
|
||||||
<target state="translated">Contatos arquivados</target>
|
<target state="translated">Contatos arquivados</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Cellular" xml:space="preserve" approved="no">
|
||||||
|
<source>Cellular</source>
|
||||||
|
<target state="translated">Rede móvel</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 arquivo(s) falharam ao ser baixados.</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 arquivo(s) foram apagados.</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 mensagens não encaminhadas</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Bad desktop address" xml:space="preserve" approved="no">
|
||||||
|
<source>Bad desktop address</source>
|
||||||
|
<target state="translated">Endereço de desktop incorreto</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Blur for better privacy." xml:space="preserve" approved="no">
|
||||||
|
<source>Blur for better privacy.</source>
|
||||||
|
<target state="translated">Borrar para melhor privacidade.</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 arquivo(s) ainda estão sendo baixados.</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 arquivo(s) não foram baixados.</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat colors" xml:space="preserve" approved="no">
|
||||||
|
<source>Chat colors</source>
|
||||||
|
<target state="translated">Cores do chat</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="%lld group events" xml:space="preserve" approved="no">
|
||||||
|
<source>%lld group events</source>
|
||||||
|
<target state="translated">%lld eventos do grupo</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="%lld messages moderated by %@" xml:space="preserve" approved="no">
|
||||||
|
<source>%lld messages moderated by %@</source>
|
||||||
|
<target state="translated">%lld mensagens moderadas por %@</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="%lld new interface languages" xml:space="preserve" approved="no">
|
||||||
|
<source>%lld new interface languages</source>
|
||||||
|
<target state="translated">%lld novos idiomas de interface</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better networking" xml:space="preserve" approved="no">
|
||||||
|
<source>Better networking</source>
|
||||||
|
<target state="translated">Melhores redes</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve" approved="no">
|
||||||
|
<source>Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source>
|
||||||
|
<target state="translated">Búlgaro, Finlandês, Tailandês e Ucraniano - obrigado aos usuários e [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better groups" xml:space="preserve" approved="no">
|
||||||
|
<source>Better groups</source>
|
||||||
|
<target state="translated">Melhores grupos</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Capacity exceeded - recipient did not receive previously sent messages." xml:space="preserve" approved="no">
|
||||||
|
<source>Capacity exceeded - recipient did not receive previously sent messages.</source>
|
||||||
|
<target state="translated">Capacidade excedida - o destinatário não recebeu as mensagens enviadas anteriormente.</target>
|
||||||
|
</trans-unit>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="pt-BR" datatype="plaintext">
|
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="pt-BR" datatype="plaintext">
|
||||||
|
|||||||
@@ -139,6 +139,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%@, %@" xml:space="preserve">
|
<trans-unit id="%@, %@" xml:space="preserve">
|
||||||
<source>%1$@, %2$@</source>
|
<source>%1$@, %2$@</source>
|
||||||
|
<target>%1$@, %2$@</target>
|
||||||
<note>format for date separator in chat</note>
|
<note>format for date separator in chat</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%@, %@ and %lld members" xml:space="preserve">
|
<trans-unit id="%@, %@ and %lld members" xml:space="preserve">
|
||||||
@@ -163,18 +164,22 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
|
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
|
||||||
<source>%d file(s) are still being downloaded.</source>
|
<source>%d file(s) are still being downloaded.</source>
|
||||||
|
<target>%d файл(ов) загружаются.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
|
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
|
||||||
<source>%d file(s) failed to download.</source>
|
<source>%d file(s) failed to download.</source>
|
||||||
|
<target>%d файл(ов) не удалось загрузить.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
|
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
|
||||||
<source>%d file(s) were deleted.</source>
|
<source>%d file(s) were deleted.</source>
|
||||||
|
<target>%d файлов было удалено.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
|
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
|
||||||
<source>%d file(s) were not downloaded.</source>
|
<source>%d file(s) were not downloaded.</source>
|
||||||
|
<target>%d файлов не было загружено.</target>
|
||||||
<note>forward confirmation reason</note>
|
<note>forward confirmation reason</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d hours" xml:space="preserve">
|
<trans-unit id="%d hours" xml:space="preserve">
|
||||||
@@ -184,6 +189,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d messages not forwarded" xml:space="preserve">
|
<trans-unit id="%d messages not forwarded" xml:space="preserve">
|
||||||
<source>%d messages not forwarded</source>
|
<source>%d messages not forwarded</source>
|
||||||
|
<target>%d сообщений не переслано</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%d min" xml:space="preserve">
|
<trans-unit id="%d min" xml:space="preserve">
|
||||||
@@ -747,7 +753,7 @@
|
|||||||
<trans-unit id="All profiles" xml:space="preserve">
|
<trans-unit id="All profiles" xml:space="preserve">
|
||||||
<source>All profiles</source>
|
<source>All profiles</source>
|
||||||
<target>Все профили</target>
|
<target>Все профили</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>profile dropdown</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||||
<source>All your contacts will remain connected.</source>
|
<source>All your contacts will remain connected.</source>
|
||||||
@@ -939,6 +945,11 @@
|
|||||||
<target>Код доступа в приложение будет заменен кодом самоуничтожения.</target>
|
<target>Код доступа в приложение будет заменен кодом самоуничтожения.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="App session" xml:space="preserve">
|
||||||
|
<source>App session</source>
|
||||||
|
<target>Сессия приложения</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="App version" xml:space="preserve">
|
<trans-unit id="App version" xml:space="preserve">
|
||||||
<source>App version</source>
|
<source>App version</source>
|
||||||
<target>Версия приложения</target>
|
<target>Версия приложения</target>
|
||||||
@@ -1046,6 +1057,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Auto-accept settings" xml:space="preserve">
|
<trans-unit id="Auto-accept settings" xml:space="preserve">
|
||||||
<source>Auto-accept settings</source>
|
<source>Auto-accept settings</source>
|
||||||
|
<target>Настройки автоприема</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Back" xml:space="preserve">
|
<trans-unit id="Back" xml:space="preserve">
|
||||||
@@ -1073,11 +1085,21 @@
|
|||||||
<target>Ошибка хэш сообщения</target>
|
<target>Ошибка хэш сообщения</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better calls" xml:space="preserve">
|
||||||
|
<source>Better calls</source>
|
||||||
|
<target>Улучшенные звонки</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better groups" xml:space="preserve">
|
<trans-unit id="Better groups" xml:space="preserve">
|
||||||
<source>Better groups</source>
|
<source>Better groups</source>
|
||||||
<target>Улучшенные группы</target>
|
<target>Улучшенные группы</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better message dates." xml:space="preserve">
|
||||||
|
<source>Better message dates.</source>
|
||||||
|
<target>Улучшенные даты сообщений.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better messages" xml:space="preserve">
|
<trans-unit id="Better messages" xml:space="preserve">
|
||||||
<source>Better messages</source>
|
<source>Better messages</source>
|
||||||
<target>Улучшенные сообщения</target>
|
<target>Улучшенные сообщения</target>
|
||||||
@@ -1088,6 +1110,21 @@
|
|||||||
<target>Улучшенные сетевые функции</target>
|
<target>Улучшенные сетевые функции</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better notifications" xml:space="preserve">
|
||||||
|
<source>Better notifications</source>
|
||||||
|
<target>Улучшенные уведомления</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||||
|
<source>Better security ✅</source>
|
||||||
|
<target>Улучшенная безопасность ✅</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better user experience" xml:space="preserve">
|
||||||
|
<source>Better user experience</source>
|
||||||
|
<target>Улучшенный интерфейс</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Black" xml:space="preserve">
|
<trans-unit id="Black" xml:space="preserve">
|
||||||
<source>Black</source>
|
<source>Black</source>
|
||||||
<target>Черная</target>
|
<target>Черная</target>
|
||||||
@@ -1371,8 +1408,14 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Chat preferences were changed." xml:space="preserve">
|
<trans-unit id="Chat preferences were changed." xml:space="preserve">
|
||||||
<source>Chat preferences were changed.</source>
|
<source>Chat preferences were changed.</source>
|
||||||
|
<target>Настройки чата были изменены.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat profile" xml:space="preserve">
|
||||||
|
<source>Chat profile</source>
|
||||||
|
<target>Профиль чата</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Chat theme" xml:space="preserve">
|
<trans-unit id="Chat theme" xml:space="preserve">
|
||||||
<source>Chat theme</source>
|
<source>Chat theme</source>
|
||||||
<target>Тема чата</target>
|
<target>Тема чата</target>
|
||||||
@@ -1774,6 +1817,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Corner" xml:space="preserve">
|
<trans-unit id="Corner" xml:space="preserve">
|
||||||
<source>Corner</source>
|
<source>Corner</source>
|
||||||
|
<target>Угол</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Correct name to %@?" xml:space="preserve">
|
<trans-unit id="Correct name to %@?" xml:space="preserve">
|
||||||
@@ -1901,6 +1945,11 @@ This is your own one-time link!</source>
|
|||||||
<target>Пользовательское время</target>
|
<target>Пользовательское время</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Customizable message shape." xml:space="preserve">
|
||||||
|
<source>Customizable message shape.</source>
|
||||||
|
<target>Настраиваемая форма сообщений.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Customize theme" xml:space="preserve">
|
<trans-unit id="Customize theme" xml:space="preserve">
|
||||||
<source>Customize theme</source>
|
<source>Customize theme</source>
|
||||||
<target>Настроить тему</target>
|
<target>Настроить тему</target>
|
||||||
@@ -2195,6 +2244,11 @@ This is your own one-time link!</source>
|
|||||||
<target>Удалить предыдущую версию данных?</target>
|
<target>Удалить предыдущую версию данных?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Delete or moderate up to 200 messages." xml:space="preserve">
|
||||||
|
<source>Delete or moderate up to 200 messages.</source>
|
||||||
|
<target>Удаляйте или модерируйте до 200 сообщений.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
||||||
<source>Delete pending connection?</source>
|
<source>Delete pending connection?</source>
|
||||||
<target>Удалить ожидаемое соединение?</target>
|
<target>Удалить ожидаемое соединение?</target>
|
||||||
@@ -2447,6 +2501,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
|
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
|
||||||
<source>Do not use credentials with proxy.</source>
|
<source>Do not use credentials with proxy.</source>
|
||||||
|
<target>Не использовать учетные данные с прокси.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Don't create address" xml:space="preserve">
|
<trans-unit id="Don't create address" xml:space="preserve">
|
||||||
@@ -2492,6 +2547,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Download files" xml:space="preserve">
|
<trans-unit id="Download files" xml:space="preserve">
|
||||||
<source>Download files</source>
|
<source>Download files</source>
|
||||||
|
<target>Загрузить файлы</target>
|
||||||
<note>alert action</note>
|
<note>alert action</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Downloaded" xml:space="preserve">
|
<trans-unit id="Downloaded" xml:space="preserve">
|
||||||
@@ -2771,6 +2827,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error changing connection profile" xml:space="preserve">
|
<trans-unit id="Error changing connection profile" xml:space="preserve">
|
||||||
<source>Error changing connection profile</source>
|
<source>Error changing connection profile</source>
|
||||||
|
<target>Ошибка при изменении профиля соединения</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error changing role" xml:space="preserve">
|
<trans-unit id="Error changing role" xml:space="preserve">
|
||||||
@@ -2785,6 +2842,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error changing to incognito!" xml:space="preserve">
|
<trans-unit id="Error changing to incognito!" xml:space="preserve">
|
||||||
<source>Error changing to incognito!</source>
|
<source>Error changing to incognito!</source>
|
||||||
|
<target>Ошибка при смене на Инкогнито!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
||||||
@@ -2909,6 +2967,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error migrating settings" xml:space="preserve">
|
<trans-unit id="Error migrating settings" xml:space="preserve">
|
||||||
<source>Error migrating settings</source>
|
<source>Error migrating settings</source>
|
||||||
|
<target>Ошибка миграции настроек</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error opening chat" xml:space="preserve">
|
<trans-unit id="Error opening chat" xml:space="preserve">
|
||||||
@@ -3013,12 +3072,13 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error switching profile" xml:space="preserve">
|
<trans-unit id="Error switching profile" xml:space="preserve">
|
||||||
<source>Error switching profile</source>
|
<source>Error switching profile</source>
|
||||||
|
<target>Ошибка переключения профиля</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error switching profile!" xml:space="preserve">
|
<trans-unit id="Error switching profile!" xml:space="preserve">
|
||||||
<source>Error switching profile!</source>
|
<source>Error switching profile!</source>
|
||||||
<target>Ошибка выбора профиля!</target>
|
<target>Ошибка выбора профиля!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>alertTitle</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
||||||
<source>Error synchronizing connection</source>
|
<source>Error synchronizing connection</source>
|
||||||
@@ -3063,8 +3123,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>Ошибка: %@</target>
|
<target>Ошибка: %@</target>
|
||||||
<note>file error text
|
<note>alert message</note>
|
||||||
snd error text</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
||||||
<source>Error: URL is invalid</source>
|
<source>Error: URL is invalid</source>
|
||||||
@@ -3154,6 +3213,8 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="File errors: %@" xml:space="preserve">
|
<trans-unit id="File errors: %@" xml:space="preserve">
|
||||||
<source>File errors:
|
<source>File errors:
|
||||||
%@</source>
|
%@</source>
|
||||||
|
<target>Ошибки файлов:
|
||||||
|
%@</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||||
@@ -3293,6 +3354,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
|
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
|
||||||
<source>Forward %d message(s)?</source>
|
<source>Forward %d message(s)?</source>
|
||||||
|
<target>Переслать %d сообщение(й)?</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward and save messages" xml:space="preserve">
|
<trans-unit id="Forward and save messages" xml:space="preserve">
|
||||||
@@ -3302,12 +3364,19 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward messages" xml:space="preserve">
|
<trans-unit id="Forward messages" xml:space="preserve">
|
||||||
<source>Forward messages</source>
|
<source>Forward messages</source>
|
||||||
|
<target>Переслать сообщения</target>
|
||||||
<note>alert action</note>
|
<note>alert action</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forward messages without files?" xml:space="preserve">
|
<trans-unit id="Forward messages without files?" xml:space="preserve">
|
||||||
<source>Forward messages without files?</source>
|
<source>Forward messages without files?</source>
|
||||||
|
<target>Переслать сообщения без файлов?</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Forward up to 20 messages at once." xml:space="preserve">
|
||||||
|
<source>Forward up to 20 messages at once.</source>
|
||||||
|
<target>Пересылайте до 20 сообщений за раз.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Forwarded" xml:space="preserve">
|
<trans-unit id="Forwarded" xml:space="preserve">
|
||||||
<source>Forwarded</source>
|
<source>Forwarded</source>
|
||||||
<target>Переслано</target>
|
<target>Переслано</target>
|
||||||
@@ -3320,6 +3389,7 @@ This is your own one-time link!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
|
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
|
||||||
<source>Forwarding %lld messages</source>
|
<source>Forwarding %lld messages</source>
|
||||||
|
<target>Пересылка %lld сообщений</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
|
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
|
||||||
@@ -3618,6 +3688,7 @@ Error: %2$@</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="IP address" xml:space="preserve">
|
<trans-unit id="IP address" xml:space="preserve">
|
||||||
<source>IP address</source>
|
<source>IP address</source>
|
||||||
|
<target>IP адрес</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
|
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
|
||||||
@@ -3695,6 +3766,12 @@ Error: %2$@</source>
|
|||||||
<target>Импорт архива</target>
|
<target>Импорт архива</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Improved delivery, reduced traffic usage. More improvements are coming soon!" xml:space="preserve">
|
||||||
|
<source>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</source>
|
||||||
|
<target>Улучшенная доставка, меньше трафик.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Improved message delivery" xml:space="preserve">
|
<trans-unit id="Improved message delivery" xml:space="preserve">
|
||||||
<source>Improved message delivery</source>
|
<source>Improved message delivery</source>
|
||||||
<target>Улучшенная доставка сообщений</target>
|
<target>Улучшенная доставка сообщений</target>
|
||||||
@@ -4267,6 +4344,7 @@ This is your link for group %@!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Message shape" xml:space="preserve">
|
<trans-unit id="Message shape" xml:space="preserve">
|
||||||
<source>Message shape</source>
|
<source>Message shape</source>
|
||||||
|
<target>Форма сообщений</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Message source remains private." xml:space="preserve">
|
<trans-unit id="Message source remains private." xml:space="preserve">
|
||||||
@@ -4321,6 +4399,7 @@ This is your link for group %@!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
|
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
|
||||||
<source>Messages were deleted after you selected them.</source>
|
<source>Messages were deleted after you selected them.</source>
|
||||||
|
<target>Сообщения были удалены после того, как вы их выбрали.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</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">
|
<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">
|
||||||
@@ -4478,6 +4557,16 @@ This is your link for group %@!</source>
|
|||||||
<target>Новый Код</target>
|
<target>Новый Код</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used every time you start the app." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used every time you start the app.</source>
|
||||||
|
<target>Новые учетные данные SOCKS будут использоваться при каждом запуске приложения.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used for each server." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used for each server.</source>
|
||||||
|
<target>Новые учетные данные SOCKS будут использоваться для каждого сервера.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="New chat" xml:space="preserve">
|
<trans-unit id="New chat" xml:space="preserve">
|
||||||
<source>New chat</source>
|
<source>New chat</source>
|
||||||
<target>Новый чат</target>
|
<target>Новый чат</target>
|
||||||
@@ -4598,6 +4687,16 @@ This is your link for group %@!</source>
|
|||||||
<target>Нет интернет-соединения</target>
|
<target>Нет интернет-соединения</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record speech" xml:space="preserve">
|
||||||
|
<source>No permission to record speech</source>
|
||||||
|
<target>Нет разрешения на запись речи</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record video" xml:space="preserve">
|
||||||
|
<source>No permission to record video</source>
|
||||||
|
<target>Нет разрешения на запись видео</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
||||||
<source>No permission to record voice message</source>
|
<source>No permission to record voice message</source>
|
||||||
<target>Нет разрешения для записи голосового сообщения</target>
|
<target>Нет разрешения для записи голосового сообщения</target>
|
||||||
@@ -4620,6 +4719,7 @@ This is your link for group %@!</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Nothing to forward!" xml:space="preserve">
|
<trans-unit id="Nothing to forward!" xml:space="preserve">
|
||||||
<source>Nothing to forward!</source>
|
<source>Nothing to forward!</source>
|
||||||
|
<target>Нет сообщений, которые можно переслать!</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Notifications" xml:space="preserve">
|
<trans-unit id="Notifications" xml:space="preserve">
|
||||||
@@ -4848,6 +4948,8 @@ Requires compatible VPN.</source>
|
|||||||
<trans-unit id="Other file errors: %@" xml:space="preserve">
|
<trans-unit id="Other file errors: %@" xml:space="preserve">
|
||||||
<source>Other file errors:
|
<source>Other file errors:
|
||||||
%@</source>
|
%@</source>
|
||||||
|
<target>Другие ошибки файлов:
|
||||||
|
%@</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="PING count" xml:space="preserve">
|
<trans-unit id="PING count" xml:space="preserve">
|
||||||
@@ -4887,6 +4989,7 @@ Requires compatible VPN.</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Password" xml:space="preserve">
|
<trans-unit id="Password" xml:space="preserve">
|
||||||
<source>Password</source>
|
<source>Password</source>
|
||||||
|
<target>Пароль</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Password to show" xml:space="preserve">
|
<trans-unit id="Password to show" xml:space="preserve">
|
||||||
@@ -5040,6 +5143,7 @@ Error: %@</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Port" xml:space="preserve">
|
<trans-unit id="Port" xml:space="preserve">
|
||||||
<source>Port</source>
|
<source>Port</source>
|
||||||
|
<target>Порт</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
|
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
|
||||||
@@ -5231,6 +5335,7 @@ Enable in *Network & servers* settings.</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Proxy requires password" xml:space="preserve">
|
<trans-unit id="Proxy requires password" xml:space="preserve">
|
||||||
<source>Proxy requires password</source>
|
<source>Proxy requires password</source>
|
||||||
|
<target>Прокси требует пароль</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Push notifications" xml:space="preserve">
|
<trans-unit id="Push notifications" xml:space="preserve">
|
||||||
@@ -5456,6 +5561,7 @@ Enable in *Network & servers* settings.</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Remove archive?" xml:space="preserve">
|
<trans-unit id="Remove archive?" xml:space="preserve">
|
||||||
<source>Remove archive?</source>
|
<source>Remove archive?</source>
|
||||||
|
<target>Удалить архив?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Remove image" xml:space="preserve">
|
<trans-unit id="Remove image" xml:space="preserve">
|
||||||
@@ -5640,6 +5746,7 @@ Enable in *Network & servers* settings.</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="SOCKS proxy" xml:space="preserve">
|
<trans-unit id="SOCKS proxy" xml:space="preserve">
|
||||||
<source>SOCKS proxy</source>
|
<source>SOCKS proxy</source>
|
||||||
|
<target>SOCKS прокси</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Safely receive files" xml:space="preserve">
|
<trans-unit id="Safely receive files" xml:space="preserve">
|
||||||
@@ -5730,6 +5837,7 @@ Enable in *Network & servers* settings.</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Save your profile?" xml:space="preserve">
|
<trans-unit id="Save your profile?" xml:space="preserve">
|
||||||
<source>Save your profile?</source>
|
<source>Save your profile?</source>
|
||||||
|
<target>Сохранить ваш профиль?</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Saved" xml:space="preserve">
|
<trans-unit id="Saved" xml:space="preserve">
|
||||||
@@ -5754,6 +5862,7 @@ Enable in *Network & servers* settings.</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Saving %lld messages" xml:space="preserve">
|
<trans-unit id="Saving %lld messages" xml:space="preserve">
|
||||||
<source>Saving %lld messages</source>
|
<source>Saving %lld messages</source>
|
||||||
|
<target>Сохранение %lld сообщений</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Scale" xml:space="preserve">
|
<trans-unit id="Scale" xml:space="preserve">
|
||||||
@@ -5838,6 +5947,7 @@ Enable in *Network & servers* settings.</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Select chat profile" xml:space="preserve">
|
<trans-unit id="Select chat profile" xml:space="preserve">
|
||||||
<source>Select chat profile</source>
|
<source>Select chat profile</source>
|
||||||
|
<target>Выберите профиль чата</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Selected %lld" xml:space="preserve">
|
<trans-unit id="Selected %lld" xml:space="preserve">
|
||||||
@@ -6055,6 +6165,11 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>Отправлено через прокси</target>
|
<target>Отправлено через прокси</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<target>Сервер</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Server address" xml:space="preserve">
|
<trans-unit id="Server address" xml:space="preserve">
|
||||||
<source>Server address</source>
|
<source>Server address</source>
|
||||||
<target>Адрес сервера</target>
|
<target>Адрес сервера</target>
|
||||||
@@ -6177,6 +6292,7 @@ Enable in *Network & servers* settings.</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Settings were changed." xml:space="preserve">
|
<trans-unit id="Settings were changed." xml:space="preserve">
|
||||||
<source>Settings were changed.</source>
|
<source>Settings were changed.</source>
|
||||||
|
<target>Настройки были изменены.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Shape profile images" xml:space="preserve">
|
<trans-unit id="Shape profile images" xml:space="preserve">
|
||||||
@@ -6216,6 +6332,7 @@ Enable in *Network & servers* settings.</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Share profile" xml:space="preserve">
|
<trans-unit id="Share profile" xml:space="preserve">
|
||||||
<source>Share profile</source>
|
<source>Share profile</source>
|
||||||
|
<target>Поделиться профилем</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Share this 1-time invite link" xml:space="preserve">
|
<trans-unit id="Share this 1-time invite link" xml:space="preserve">
|
||||||
@@ -6353,6 +6470,11 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>SimpleX одноразовая ссылка</target>
|
<target>SimpleX одноразовая ссылка</target>
|
||||||
<note>simplex link type</note>
|
<note>simplex link type</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SimpleX protocols reviewed by Trail of Bits." xml:space="preserve">
|
||||||
|
<source>SimpleX protocols reviewed by Trail of Bits.</source>
|
||||||
|
<target>Аудит SimpleX протоколов от Trail of Bits.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
||||||
<source>Simplified incognito mode</source>
|
<source>Simplified incognito mode</source>
|
||||||
<target>Упрощенный режим Инкогнито</target>
|
<target>Упрощенный режим Инкогнито</target>
|
||||||
@@ -6385,6 +6507,7 @@ Enable in *Network & servers* settings.</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
|
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
|
||||||
<source>Some app settings were not migrated.</source>
|
<source>Some app settings were not migrated.</source>
|
||||||
|
<target>Некоторые настройки приложения не были перенесены.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
|
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
|
||||||
@@ -6527,6 +6650,16 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>Поддержать SimpleX Chat</target>
|
<target>Поддержать SimpleX Chat</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch audio and video during the call." xml:space="preserve">
|
||||||
|
<source>Switch audio and video during the call.</source>
|
||||||
|
<target>Переключайте звук и видео во время звонка.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch chat profile for 1-time invitations." xml:space="preserve">
|
||||||
|
<source>Switch chat profile for 1-time invitations.</source>
|
||||||
|
<target>Переключайте профиль чата для одноразовых приглашений.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="System" xml:space="preserve">
|
<trans-unit id="System" xml:space="preserve">
|
||||||
<source>System</source>
|
<source>System</source>
|
||||||
<target>Системная</target>
|
<target>Системная</target>
|
||||||
@@ -6564,6 +6697,7 @@ Enable in *Network & servers* settings.</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Tail" xml:space="preserve">
|
<trans-unit id="Tail" xml:space="preserve">
|
||||||
<source>Tail</source>
|
<source>Tail</source>
|
||||||
|
<target>Хвост</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Take picture" xml:space="preserve">
|
<trans-unit id="Take picture" xml:space="preserve">
|
||||||
@@ -6760,6 +6894,7 @@ It can happen because of some bug or when the connection is compromised.</source
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
|
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
|
||||||
<source>The uploaded database archive will be permanently removed from the servers.</source>
|
<source>The uploaded database archive will be permanently removed from the servers.</source>
|
||||||
|
<target>Загруженный архив базы данных будет навсегда удален с серверов.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Themes" xml:space="preserve">
|
<trans-unit id="Themes" xml:space="preserve">
|
||||||
@@ -6889,6 +7024,16 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||||||
Вам будет нужно пройти аутентификацию для включения блокировки.</target>
|
Вам будет нужно пройти аутентификацию для включения блокировки.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="To record speech please grant permission to use Microphone." xml:space="preserve">
|
||||||
|
<source>To record speech please grant permission to use Microphone.</source>
|
||||||
|
<target>Для записи речи, пожалуйста, дайте разрешение на использование микрофона.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="To record video please grant permission to use Camera." xml:space="preserve">
|
||||||
|
<source>To record video please grant permission to use Camera.</source>
|
||||||
|
<target>Для записи видео, пожалуйста, дайте разрешение на использование камеры.</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
||||||
<source>To record voice message please grant permission to use Microphone.</source>
|
<source>To record voice message please grant permission to use Microphone.</source>
|
||||||
<target>Для записи голосового сообщения, пожалуйста разрешите доступ к микрофону.</target>
|
<target>Для записи голосового сообщения, пожалуйста разрешите доступ к микрофону.</target>
|
||||||
@@ -7158,6 +7303,7 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
|
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
|
||||||
<source>Use SOCKS proxy</source>
|
<source>Use SOCKS proxy</source>
|
||||||
|
<target>Использовать SOCKS прокси</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
|
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
|
||||||
@@ -7225,11 +7371,6 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
<target>Используйте приложение одной рукой.</target>
|
<target>Используйте приложение одной рукой.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User profile" xml:space="preserve">
|
|
||||||
<source>User profile</source>
|
|
||||||
<target>Профиль чата</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User selection" xml:space="preserve">
|
<trans-unit id="User selection" xml:space="preserve">
|
||||||
<source>User selection</source>
|
<source>User selection</source>
|
||||||
<target>Выбор пользователя</target>
|
<target>Выбор пользователя</target>
|
||||||
@@ -7237,6 +7378,7 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Username" xml:space="preserve">
|
<trans-unit id="Username" xml:space="preserve">
|
||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
|
<target>Имя пользователя</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
|
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
|
||||||
@@ -7499,11 +7641,6 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
<target>XFTP сервер</target>
|
<target>XFTP сервер</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="You" xml:space="preserve">
|
|
||||||
<source>You</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">
|
<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>
|
<source>You **must not** use the same database on two devices.</source>
|
||||||
<target>Вы **не должны** использовать одну и ту же базу данных на двух устройствах.</target>
|
<target>Вы **не должны** использовать одну и ту же базу данных на двух устройствах.</target>
|
||||||
@@ -7855,6 +7992,7 @@ Repeat connection request?</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your chat preferences" xml:space="preserve">
|
<trans-unit id="Your chat preferences" xml:space="preserve">
|
||||||
<source>Your chat preferences</source>
|
<source>Your chat preferences</source>
|
||||||
|
<target>Ваши настройки чата</target>
|
||||||
<note>alert title</note>
|
<note>alert title</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your chat profiles" xml:space="preserve">
|
<trans-unit id="Your chat profiles" xml:space="preserve">
|
||||||
@@ -7864,6 +8002,7 @@ Repeat connection request?</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile." xml:space="preserve">
|
<trans-unit id="Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile." xml:space="preserve">
|
||||||
<source>Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile.</source>
|
<source>Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile.</source>
|
||||||
|
<target>Соединение было перемещено на %@, но при смене профиля произошла неожиданная ошибка.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your contact sent a file that is larger than currently supported maximum size (%@)." xml:space="preserve">
|
<trans-unit id="Your contact sent a file that is larger than currently supported maximum size (%@)." xml:space="preserve">
|
||||||
@@ -7883,6 +8022,7 @@ Repeat connection request?</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
|
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
|
||||||
<source>Your credentials may be sent unencrypted.</source>
|
<source>Your credentials may be sent unencrypted.</source>
|
||||||
|
<target>Ваши учетные данные могут быть отправлены в незашифрованном виде.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
|
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
|
||||||
@@ -7922,6 +8062,7 @@ Repeat connection request?</source>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
|
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
|
||||||
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
|
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
|
||||||
|
<target>Ваш профиль был изменен. Если вы сохраните его, обновленный профиль будет отправлен всем вашим контактам.</target>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
|
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
|
||||||
|
|||||||
@@ -702,7 +702,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All profiles" xml:space="preserve">
|
<trans-unit id="All profiles" xml:space="preserve">
|
||||||
<source>All profiles</source>
|
<source>All profiles</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>profile dropdown</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||||
<source>All your contacts will remain connected.</source>
|
<source>All your contacts will remain connected.</source>
|
||||||
@@ -884,6 +884,10 @@
|
|||||||
<target>รหัสผ่านแอปจะถูกแทนที่ด้วยรหัสผ่านที่ทำลายตัวเอง</target>
|
<target>รหัสผ่านแอปจะถูกแทนที่ด้วยรหัสผ่านที่ทำลายตัวเอง</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="App session" xml:space="preserve">
|
||||||
|
<source>App session</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="App version" xml:space="preserve">
|
<trans-unit id="App version" xml:space="preserve">
|
||||||
<source>App version</source>
|
<source>App version</source>
|
||||||
<target>เวอร์ชันแอป</target>
|
<target>เวอร์ชันแอป</target>
|
||||||
@@ -1010,10 +1014,18 @@
|
|||||||
<target>แฮชข้อความไม่ดี</target>
|
<target>แฮชข้อความไม่ดี</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better calls" xml:space="preserve">
|
||||||
|
<source>Better calls</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better groups" xml:space="preserve">
|
<trans-unit id="Better groups" xml:space="preserve">
|
||||||
<source>Better groups</source>
|
<source>Better groups</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better message dates." xml:space="preserve">
|
||||||
|
<source>Better message dates.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better messages" xml:space="preserve">
|
<trans-unit id="Better messages" xml:space="preserve">
|
||||||
<source>Better messages</source>
|
<source>Better messages</source>
|
||||||
<target>ข้อความที่ดีขึ้น</target>
|
<target>ข้อความที่ดีขึ้น</target>
|
||||||
@@ -1023,6 +1035,18 @@
|
|||||||
<source>Better networking</source>
|
<source>Better networking</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better notifications" xml:space="preserve">
|
||||||
|
<source>Better notifications</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||||
|
<source>Better security ✅</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better user experience" xml:space="preserve">
|
||||||
|
<source>Better user experience</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Black" xml:space="preserve">
|
<trans-unit id="Black" xml:space="preserve">
|
||||||
<source>Black</source>
|
<source>Black</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -1283,6 +1307,11 @@
|
|||||||
<source>Chat preferences were changed.</source>
|
<source>Chat preferences were changed.</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat profile" xml:space="preserve">
|
||||||
|
<source>Chat profile</source>
|
||||||
|
<target>โปรไฟล์ผู้ใช้</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Chat theme" xml:space="preserve">
|
<trans-unit id="Chat theme" xml:space="preserve">
|
||||||
<source>Chat theme</source>
|
<source>Chat theme</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -1756,6 +1785,10 @@ This is your own one-time link!</source>
|
|||||||
<target>เวลาที่กําหนดเอง</target>
|
<target>เวลาที่กําหนดเอง</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Customizable message shape." xml:space="preserve">
|
||||||
|
<source>Customizable message shape.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Customize theme" xml:space="preserve">
|
<trans-unit id="Customize theme" xml:space="preserve">
|
||||||
<source>Customize theme</source>
|
<source>Customize theme</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -2042,6 +2075,10 @@ This is your own one-time link!</source>
|
|||||||
<target>ลบฐานข้อมูลเก่า?</target>
|
<target>ลบฐานข้อมูลเก่า?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Delete or moderate up to 200 messages." xml:space="preserve">
|
||||||
|
<source>Delete or moderate up to 200 messages.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
||||||
<source>Delete pending connection?</source>
|
<source>Delete pending connection?</source>
|
||||||
<target>ลบการเชื่อมต่อที่รอดำเนินการหรือไม่?</target>
|
<target>ลบการเชื่อมต่อที่รอดำเนินการหรือไม่?</target>
|
||||||
@@ -2811,7 +2848,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error switching profile!" xml:space="preserve">
|
<trans-unit id="Error switching profile!" xml:space="preserve">
|
||||||
<source>Error switching profile!</source>
|
<source>Error switching profile!</source>
|
||||||
<target>เกิดข้อผิดพลาดในการเปลี่ยนโปรไฟล์!</target>
|
<target>เกิดข้อผิดพลาดในการเปลี่ยนโปรไฟล์!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>alertTitle</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
||||||
<source>Error synchronizing connection</source>
|
<source>Error synchronizing connection</source>
|
||||||
@@ -2854,8 +2891,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>ข้อผิดพลาด: % @</target>
|
<target>ข้อผิดพลาด: % @</target>
|
||||||
<note>file error text
|
<note>alert message</note>
|
||||||
snd error text</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
||||||
<source>Error: URL is invalid</source>
|
<source>Error: URL is invalid</source>
|
||||||
@@ -3083,6 +3119,10 @@ This is your own one-time link!</source>
|
|||||||
<source>Forward messages without files?</source>
|
<source>Forward messages without files?</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Forward up to 20 messages at once." xml:space="preserve">
|
||||||
|
<source>Forward up to 20 messages at once.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Forwarded" xml:space="preserve">
|
<trans-unit id="Forwarded" xml:space="preserve">
|
||||||
<source>Forwarded</source>
|
<source>Forwarded</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -3449,6 +3489,11 @@ Error: %2$@</source>
|
|||||||
<source>Importing archive</source>
|
<source>Importing archive</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Improved delivery, reduced traffic usage. More improvements are coming soon!" xml:space="preserve">
|
||||||
|
<source>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Improved message delivery" xml:space="preserve">
|
<trans-unit id="Improved message delivery" xml:space="preserve">
|
||||||
<source>Improved message delivery</source>
|
<source>Improved message delivery</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -4174,6 +4219,14 @@ This is your link for group %@!</source>
|
|||||||
<target>รหัสผ่านใหม่</target>
|
<target>รหัสผ่านใหม่</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used every time you start the app." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used every time you start the app.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used for each server." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used for each server.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="New chat" xml:space="preserve">
|
<trans-unit id="New chat" xml:space="preserve">
|
||||||
<source>New chat</source>
|
<source>New chat</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -4286,6 +4339,14 @@ This is your link for group %@!</source>
|
|||||||
<source>No network connection</source>
|
<source>No network connection</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record speech" xml:space="preserve">
|
||||||
|
<source>No permission to record speech</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record video" xml:space="preserve">
|
||||||
|
<source>No permission to record video</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
||||||
<source>No permission to record voice message</source>
|
<source>No permission to record voice message</source>
|
||||||
<target>ไม่อนุญาตให้บันทึกข้อความเสียง</target>
|
<target>ไม่อนุญาตให้บันทึกข้อความเสียง</target>
|
||||||
@@ -5641,6 +5702,10 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<source>Sent via proxy</source>
|
<source>Sent via proxy</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Server address" xml:space="preserve">
|
<trans-unit id="Server address" xml:space="preserve">
|
||||||
<source>Server address</source>
|
<source>Server address</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -5916,6 +5981,10 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>คำเชิญ SimpleX แบบครั้งเดียว</target>
|
<target>คำเชิญ SimpleX แบบครั้งเดียว</target>
|
||||||
<note>simplex link type</note>
|
<note>simplex link type</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SimpleX protocols reviewed by Trail of Bits." xml:space="preserve">
|
||||||
|
<source>SimpleX protocols reviewed by Trail of Bits.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
||||||
<source>Simplified incognito mode</source>
|
<source>Simplified incognito mode</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -6074,6 +6143,14 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>สนับสนุน SimpleX แชท</target>
|
<target>สนับสนุน SimpleX แชท</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch audio and video during the call." xml:space="preserve">
|
||||||
|
<source>Switch audio and video during the call.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch chat profile for 1-time invitations." xml:space="preserve">
|
||||||
|
<source>Switch chat profile for 1-time invitations.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="System" xml:space="preserve">
|
<trans-unit id="System" xml:space="preserve">
|
||||||
<source>System</source>
|
<source>System</source>
|
||||||
<target>ระบบ</target>
|
<target>ระบบ</target>
|
||||||
@@ -6414,6 +6491,14 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||||||
คุณจะได้รับแจ้งให้ยืนยันตัวตนให้เสร็จสมบูรณ์ก่อนที่จะเปิดใช้งานคุณลักษณะนี้</target>
|
คุณจะได้รับแจ้งให้ยืนยันตัวตนให้เสร็จสมบูรณ์ก่อนที่จะเปิดใช้งานคุณลักษณะนี้</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="To record speech please grant permission to use Microphone." xml:space="preserve">
|
||||||
|
<source>To record speech please grant permission to use Microphone.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="To record video please grant permission to use Camera." xml:space="preserve">
|
||||||
|
<source>To record video please grant permission to use Camera.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
||||||
<source>To record voice message please grant permission to use Microphone.</source>
|
<source>To record voice message please grant permission to use Microphone.</source>
|
||||||
<target>ในการบันทึกข้อความเสียง โปรดให้สิทธิ์ในการใช้ไมโครโฟน</target>
|
<target>ในการบันทึกข้อความเสียง โปรดให้สิทธิ์ในการใช้ไมโครโฟน</target>
|
||||||
@@ -6721,11 +6806,6 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
<source>Use the app with one hand.</source>
|
<source>Use the app with one hand.</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User profile" xml:space="preserve">
|
|
||||||
<source>User profile</source>
|
|
||||||
<target>โปรไฟล์ผู้ใช้</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User selection" xml:space="preserve">
|
<trans-unit id="User selection" xml:space="preserve">
|
||||||
<source>User selection</source>
|
<source>User selection</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
@@ -6970,11 +7050,6 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
<source>XFTP server</source>
|
<source>XFTP server</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="You" xml:space="preserve">
|
|
||||||
<source>You</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">
|
<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>
|
<source>You **must not** use the same database on two devices.</source>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -747,7 +747,7 @@
|
|||||||
<trans-unit id="All profiles" xml:space="preserve">
|
<trans-unit id="All profiles" xml:space="preserve">
|
||||||
<source>All profiles</source>
|
<source>All profiles</source>
|
||||||
<target>Всі профілі</target>
|
<target>Всі профілі</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>profile dropdown</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||||
<source>All your contacts will remain connected.</source>
|
<source>All your contacts will remain connected.</source>
|
||||||
@@ -939,6 +939,10 @@
|
|||||||
<target>Пароль програми замінено на пароль самознищення.</target>
|
<target>Пароль програми замінено на пароль самознищення.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="App session" xml:space="preserve">
|
||||||
|
<source>App session</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="App version" xml:space="preserve">
|
<trans-unit id="App version" xml:space="preserve">
|
||||||
<source>App version</source>
|
<source>App version</source>
|
||||||
<target>Версія програми</target>
|
<target>Версія програми</target>
|
||||||
@@ -1073,11 +1077,19 @@
|
|||||||
<target>Поганий хеш повідомлення</target>
|
<target>Поганий хеш повідомлення</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better calls" xml:space="preserve">
|
||||||
|
<source>Better calls</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better groups" xml:space="preserve">
|
<trans-unit id="Better groups" xml:space="preserve">
|
||||||
<source>Better groups</source>
|
<source>Better groups</source>
|
||||||
<target>Кращі групи</target>
|
<target>Кращі групи</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better message dates." xml:space="preserve">
|
||||||
|
<source>Better message dates.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better messages" xml:space="preserve">
|
<trans-unit id="Better messages" xml:space="preserve">
|
||||||
<source>Better messages</source>
|
<source>Better messages</source>
|
||||||
<target>Кращі повідомлення</target>
|
<target>Кращі повідомлення</target>
|
||||||
@@ -1088,6 +1100,18 @@
|
|||||||
<target>Краща мережа</target>
|
<target>Краща мережа</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better notifications" xml:space="preserve">
|
||||||
|
<source>Better notifications</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||||
|
<source>Better security ✅</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better user experience" xml:space="preserve">
|
||||||
|
<source>Better user experience</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Black" xml:space="preserve">
|
<trans-unit id="Black" xml:space="preserve">
|
||||||
<source>Black</source>
|
<source>Black</source>
|
||||||
<target>Чорний</target>
|
<target>Чорний</target>
|
||||||
@@ -1373,6 +1397,11 @@
|
|||||||
<source>Chat preferences were changed.</source>
|
<source>Chat preferences were changed.</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat profile" xml:space="preserve">
|
||||||
|
<source>Chat profile</source>
|
||||||
|
<target>Профіль користувача</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Chat theme" xml:space="preserve">
|
<trans-unit id="Chat theme" xml:space="preserve">
|
||||||
<source>Chat theme</source>
|
<source>Chat theme</source>
|
||||||
<target>Тема чату</target>
|
<target>Тема чату</target>
|
||||||
@@ -1901,6 +1930,10 @@ This is your own one-time link!</source>
|
|||||||
<target>Індивідуальний час</target>
|
<target>Індивідуальний час</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Customizable message shape." xml:space="preserve">
|
||||||
|
<source>Customizable message shape.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Customize theme" xml:space="preserve">
|
<trans-unit id="Customize theme" xml:space="preserve">
|
||||||
<source>Customize theme</source>
|
<source>Customize theme</source>
|
||||||
<target>Налаштувати тему</target>
|
<target>Налаштувати тему</target>
|
||||||
@@ -2195,6 +2228,10 @@ This is your own one-time link!</source>
|
|||||||
<target>Видалити стару базу даних?</target>
|
<target>Видалити стару базу даних?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Delete or moderate up to 200 messages." xml:space="preserve">
|
||||||
|
<source>Delete or moderate up to 200 messages.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
||||||
<source>Delete pending connection?</source>
|
<source>Delete pending connection?</source>
|
||||||
<target>Видалити очікуване з'єднання?</target>
|
<target>Видалити очікуване з'єднання?</target>
|
||||||
@@ -3018,7 +3055,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error switching profile!" xml:space="preserve">
|
<trans-unit id="Error switching profile!" xml:space="preserve">
|
||||||
<source>Error switching profile!</source>
|
<source>Error switching profile!</source>
|
||||||
<target>Помилка перемикання профілю!</target>
|
<target>Помилка перемикання профілю!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>alertTitle</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
||||||
<source>Error synchronizing connection</source>
|
<source>Error synchronizing connection</source>
|
||||||
@@ -3063,8 +3100,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>Помилка: %@</target>
|
<target>Помилка: %@</target>
|
||||||
<note>file error text
|
<note>alert message</note>
|
||||||
snd error text</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
||||||
<source>Error: URL is invalid</source>
|
<source>Error: URL is invalid</source>
|
||||||
@@ -3308,6 +3344,10 @@ This is your own one-time link!</source>
|
|||||||
<source>Forward messages without files?</source>
|
<source>Forward messages without files?</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Forward up to 20 messages at once." xml:space="preserve">
|
||||||
|
<source>Forward up to 20 messages at once.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Forwarded" xml:space="preserve">
|
<trans-unit id="Forwarded" xml:space="preserve">
|
||||||
<source>Forwarded</source>
|
<source>Forwarded</source>
|
||||||
<target>Переслано</target>
|
<target>Переслано</target>
|
||||||
@@ -3695,6 +3735,11 @@ Error: %2$@</source>
|
|||||||
<target>Імпорт архіву</target>
|
<target>Імпорт архіву</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Improved delivery, reduced traffic usage. More improvements are coming soon!" xml:space="preserve">
|
||||||
|
<source>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Improved message delivery" xml:space="preserve">
|
<trans-unit id="Improved message delivery" xml:space="preserve">
|
||||||
<source>Improved message delivery</source>
|
<source>Improved message delivery</source>
|
||||||
<target>Покращена доставка повідомлень</target>
|
<target>Покращена доставка повідомлень</target>
|
||||||
@@ -4478,6 +4523,14 @@ This is your link for group %@!</source>
|
|||||||
<target>Новий пароль</target>
|
<target>Новий пароль</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used every time you start the app." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used every time you start the app.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used for each server." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used for each server.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="New chat" xml:space="preserve">
|
<trans-unit id="New chat" xml:space="preserve">
|
||||||
<source>New chat</source>
|
<source>New chat</source>
|
||||||
<target>Новий чат</target>
|
<target>Новий чат</target>
|
||||||
@@ -4598,6 +4651,14 @@ This is your link for group %@!</source>
|
|||||||
<target>Немає підключення до мережі</target>
|
<target>Немає підключення до мережі</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record speech" xml:space="preserve">
|
||||||
|
<source>No permission to record speech</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record video" xml:space="preserve">
|
||||||
|
<source>No permission to record video</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
||||||
<source>No permission to record voice message</source>
|
<source>No permission to record voice message</source>
|
||||||
<target>Немає дозволу на запис голосового повідомлення</target>
|
<target>Немає дозволу на запис голосового повідомлення</target>
|
||||||
@@ -6055,6 +6116,10 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>Відправлено через проксі</target>
|
<target>Відправлено через проксі</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Server address" xml:space="preserve">
|
<trans-unit id="Server address" xml:space="preserve">
|
||||||
<source>Server address</source>
|
<source>Server address</source>
|
||||||
<target>Адреса сервера</target>
|
<target>Адреса сервера</target>
|
||||||
@@ -6353,6 +6418,10 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>Одноразове запрошення SimpleX</target>
|
<target>Одноразове запрошення SimpleX</target>
|
||||||
<note>simplex link type</note>
|
<note>simplex link type</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SimpleX protocols reviewed by Trail of Bits." xml:space="preserve">
|
||||||
|
<source>SimpleX protocols reviewed by Trail of Bits.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
||||||
<source>Simplified incognito mode</source>
|
<source>Simplified incognito mode</source>
|
||||||
<target>Спрощений режим інкогніто</target>
|
<target>Спрощений режим інкогніто</target>
|
||||||
@@ -6527,6 +6596,14 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>Підтримка чату SimpleX</target>
|
<target>Підтримка чату SimpleX</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch audio and video during the call." xml:space="preserve">
|
||||||
|
<source>Switch audio and video during the call.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch chat profile for 1-time invitations." xml:space="preserve">
|
||||||
|
<source>Switch chat profile for 1-time invitations.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="System" xml:space="preserve">
|
<trans-unit id="System" xml:space="preserve">
|
||||||
<source>System</source>
|
<source>System</source>
|
||||||
<target>Система</target>
|
<target>Система</target>
|
||||||
@@ -6889,6 +6966,14 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||||||
Перед увімкненням цієї функції вам буде запропоновано пройти автентифікацію.</target>
|
Перед увімкненням цієї функції вам буде запропоновано пройти автентифікацію.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="To record speech please grant permission to use Microphone." xml:space="preserve">
|
||||||
|
<source>To record speech please grant permission to use Microphone.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="To record video please grant permission to use Camera." xml:space="preserve">
|
||||||
|
<source>To record video please grant permission to use Camera.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
||||||
<source>To record voice message please grant permission to use Microphone.</source>
|
<source>To record voice message please grant permission to use Microphone.</source>
|
||||||
<target>Щоб записати голосове повідомлення, будь ласка, надайте дозвіл на використання мікрофону.</target>
|
<target>Щоб записати голосове повідомлення, будь ласка, надайте дозвіл на використання мікрофону.</target>
|
||||||
@@ -7225,11 +7310,6 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
<target>Використовуйте додаток однією рукою.</target>
|
<target>Використовуйте додаток однією рукою.</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User profile" xml:space="preserve">
|
|
||||||
<source>User profile</source>
|
|
||||||
<target>Профіль користувача</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User selection" xml:space="preserve">
|
<trans-unit id="User selection" xml:space="preserve">
|
||||||
<source>User selection</source>
|
<source>User selection</source>
|
||||||
<target>Вибір користувача</target>
|
<target>Вибір користувача</target>
|
||||||
@@ -7499,11 +7579,6 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
<target>XFTP-сервер</target>
|
<target>XFTP-сервер</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="You" xml:space="preserve">
|
|
||||||
<source>You</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">
|
<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>
|
<source>You **must not** use the same database on two devices.</source>
|
||||||
<target>Ви **не повинні використовувати** одну і ту ж базу даних на двох пристроях.</target>
|
<target>Ви **не повинні використовувати** одну і ту ж базу даних на двох пристроях.</target>
|
||||||
|
|||||||
@@ -747,7 +747,7 @@
|
|||||||
<trans-unit id="All profiles" xml:space="preserve">
|
<trans-unit id="All profiles" xml:space="preserve">
|
||||||
<source>All profiles</source>
|
<source>All profiles</source>
|
||||||
<target>所有配置文件</target>
|
<target>所有配置文件</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>profile dropdown</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||||
<source>All your contacts will remain connected.</source>
|
<source>All your contacts will remain connected.</source>
|
||||||
@@ -939,6 +939,10 @@
|
|||||||
<target>应用程序密码被替换为自毁密码。</target>
|
<target>应用程序密码被替换为自毁密码。</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="App session" xml:space="preserve">
|
||||||
|
<source>App session</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="App version" xml:space="preserve">
|
<trans-unit id="App version" xml:space="preserve">
|
||||||
<source>App version</source>
|
<source>App version</source>
|
||||||
<target>应用程序版本</target>
|
<target>应用程序版本</target>
|
||||||
@@ -1073,11 +1077,19 @@
|
|||||||
<target>错误消息散列</target>
|
<target>错误消息散列</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better calls" xml:space="preserve">
|
||||||
|
<source>Better calls</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better groups" xml:space="preserve">
|
<trans-unit id="Better groups" xml:space="preserve">
|
||||||
<source>Better groups</source>
|
<source>Better groups</source>
|
||||||
<target>更佳的群组</target>
|
<target>更佳的群组</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better message dates." xml:space="preserve">
|
||||||
|
<source>Better message dates.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Better messages" xml:space="preserve">
|
<trans-unit id="Better messages" xml:space="preserve">
|
||||||
<source>Better messages</source>
|
<source>Better messages</source>
|
||||||
<target>更好的消息</target>
|
<target>更好的消息</target>
|
||||||
@@ -1088,6 +1100,18 @@
|
|||||||
<target>更好的网络</target>
|
<target>更好的网络</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Better notifications" xml:space="preserve">
|
||||||
|
<source>Better notifications</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||||
|
<source>Better security ✅</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Better user experience" xml:space="preserve">
|
||||||
|
<source>Better user experience</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Black" xml:space="preserve">
|
<trans-unit id="Black" xml:space="preserve">
|
||||||
<source>Black</source>
|
<source>Black</source>
|
||||||
<target>黑色</target>
|
<target>黑色</target>
|
||||||
@@ -1373,6 +1397,11 @@
|
|||||||
<source>Chat preferences were changed.</source>
|
<source>Chat preferences were changed.</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Chat profile" xml:space="preserve">
|
||||||
|
<source>Chat profile</source>
|
||||||
|
<target>用户资料</target>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Chat theme" xml:space="preserve">
|
<trans-unit id="Chat theme" xml:space="preserve">
|
||||||
<source>Chat theme</source>
|
<source>Chat theme</source>
|
||||||
<target>聊天主题</target>
|
<target>聊天主题</target>
|
||||||
@@ -1901,6 +1930,10 @@ This is your own one-time link!</source>
|
|||||||
<target>自定义时间</target>
|
<target>自定义时间</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Customizable message shape." xml:space="preserve">
|
||||||
|
<source>Customizable message shape.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Customize theme" xml:space="preserve">
|
<trans-unit id="Customize theme" xml:space="preserve">
|
||||||
<source>Customize theme</source>
|
<source>Customize theme</source>
|
||||||
<target>自定义主题</target>
|
<target>自定义主题</target>
|
||||||
@@ -2195,6 +2228,10 @@ This is your own one-time link!</source>
|
|||||||
<target>删除旧数据库吗?</target>
|
<target>删除旧数据库吗?</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Delete or moderate up to 200 messages." xml:space="preserve">
|
||||||
|
<source>Delete or moderate up to 200 messages.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
<trans-unit id="Delete pending connection?" xml:space="preserve">
|
||||||
<source>Delete pending connection?</source>
|
<source>Delete pending connection?</source>
|
||||||
<target>删除待定连接?</target>
|
<target>删除待定连接?</target>
|
||||||
@@ -3018,7 +3055,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error switching profile!" xml:space="preserve">
|
<trans-unit id="Error switching profile!" xml:space="preserve">
|
||||||
<source>Error switching profile!</source>
|
<source>Error switching profile!</source>
|
||||||
<target>切换资料错误!</target>
|
<target>切换资料错误!</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>alertTitle</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
<trans-unit id="Error synchronizing connection" xml:space="preserve">
|
||||||
<source>Error synchronizing connection</source>
|
<source>Error synchronizing connection</source>
|
||||||
@@ -3063,8 +3100,7 @@ This is your own one-time link!</source>
|
|||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>错误: %@</target>
|
<target>错误: %@</target>
|
||||||
<note>file error text
|
<note>alert message</note>
|
||||||
snd error text</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
<trans-unit id="Error: URL is invalid" xml:space="preserve">
|
||||||
<source>Error: URL is invalid</source>
|
<source>Error: URL is invalid</source>
|
||||||
@@ -3308,6 +3344,10 @@ This is your own one-time link!</source>
|
|||||||
<source>Forward messages without files?</source>
|
<source>Forward messages without files?</source>
|
||||||
<note>alert message</note>
|
<note>alert message</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Forward up to 20 messages at once." xml:space="preserve">
|
||||||
|
<source>Forward up to 20 messages at once.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Forwarded" xml:space="preserve">
|
<trans-unit id="Forwarded" xml:space="preserve">
|
||||||
<source>Forwarded</source>
|
<source>Forwarded</source>
|
||||||
<target>已转发</target>
|
<target>已转发</target>
|
||||||
@@ -3695,6 +3735,11 @@ Error: %2$@</source>
|
|||||||
<target>正在导入存档</target>
|
<target>正在导入存档</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Improved delivery, reduced traffic usage. More improvements are coming soon!" xml:space="preserve">
|
||||||
|
<source>Improved delivery, reduced traffic usage.
|
||||||
|
More improvements are coming soon!</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Improved message delivery" xml:space="preserve">
|
<trans-unit id="Improved message delivery" xml:space="preserve">
|
||||||
<source>Improved message delivery</source>
|
<source>Improved message delivery</source>
|
||||||
<target>改进了消息传递</target>
|
<target>改进了消息传递</target>
|
||||||
@@ -4478,6 +4523,14 @@ This is your link for group %@!</source>
|
|||||||
<target>新密码</target>
|
<target>新密码</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used every time you start the app." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used every time you start the app.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="New SOCKS credentials will be used for each server." xml:space="preserve">
|
||||||
|
<source>New SOCKS credentials will be used for each server.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="New chat" xml:space="preserve">
|
<trans-unit id="New chat" xml:space="preserve">
|
||||||
<source>New chat</source>
|
<source>New chat</source>
|
||||||
<target>新聊天</target>
|
<target>新聊天</target>
|
||||||
@@ -4598,6 +4651,14 @@ This is your link for group %@!</source>
|
|||||||
<target>无网络连接</target>
|
<target>无网络连接</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record speech" xml:space="preserve">
|
||||||
|
<source>No permission to record speech</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No permission to record video" xml:space="preserve">
|
||||||
|
<source>No permission to record video</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
<trans-unit id="No permission to record voice message" xml:space="preserve">
|
||||||
<source>No permission to record voice message</source>
|
<source>No permission to record voice message</source>
|
||||||
<target>没有录制语音消息的权限</target>
|
<target>没有录制语音消息的权限</target>
|
||||||
@@ -6055,6 +6116,10 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>通过代理发送</target>
|
<target>通过代理发送</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Server address" xml:space="preserve">
|
<trans-unit id="Server address" xml:space="preserve">
|
||||||
<source>Server address</source>
|
<source>Server address</source>
|
||||||
<target>服务器地址</target>
|
<target>服务器地址</target>
|
||||||
@@ -6353,6 +6418,10 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>SimpleX 一次性邀请</target>
|
<target>SimpleX 一次性邀请</target>
|
||||||
<note>simplex link type</note>
|
<note>simplex link type</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SimpleX protocols reviewed by Trail of Bits." xml:space="preserve">
|
||||||
|
<source>SimpleX protocols reviewed by Trail of Bits.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
<trans-unit id="Simplified incognito mode" xml:space="preserve">
|
||||||
<source>Simplified incognito mode</source>
|
<source>Simplified incognito mode</source>
|
||||||
<target>简化的隐身模式</target>
|
<target>简化的隐身模式</target>
|
||||||
@@ -6527,6 +6596,14 @@ Enable in *Network & servers* settings.</source>
|
|||||||
<target>支持 SimpleX Chat</target>
|
<target>支持 SimpleX Chat</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch audio and video during the call." xml:space="preserve">
|
||||||
|
<source>Switch audio and video during the call.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Switch chat profile for 1-time invitations." xml:space="preserve">
|
||||||
|
<source>Switch chat profile for 1-time invitations.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="System" xml:space="preserve">
|
<trans-unit id="System" xml:space="preserve">
|
||||||
<source>System</source>
|
<source>System</source>
|
||||||
<target>系统</target>
|
<target>系统</target>
|
||||||
@@ -6889,6 +6966,14 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||||||
在启用此功能之前,系统将提示您完成身份验证。</target>
|
在启用此功能之前,系统将提示您完成身份验证。</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="To record speech please grant permission to use Microphone." xml:space="preserve">
|
||||||
|
<source>To record speech please grant permission to use Microphone.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="To record video please grant permission to use Camera." xml:space="preserve">
|
||||||
|
<source>To record video please grant permission to use Camera.</source>
|
||||||
|
<note>No comment provided by engineer.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
<trans-unit id="To record voice message please grant permission to use Microphone." xml:space="preserve">
|
||||||
<source>To record voice message please grant permission to use Microphone.</source>
|
<source>To record voice message please grant permission to use Microphone.</source>
|
||||||
<target>请授权使用麦克风以录制语音消息。</target>
|
<target>请授权使用麦克风以录制语音消息。</target>
|
||||||
@@ -7225,11 +7310,6 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
<target>用一只手使用应用程序。</target>
|
<target>用一只手使用应用程序。</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User profile" xml:space="preserve">
|
|
||||||
<source>User profile</source>
|
|
||||||
<target>用户资料</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User selection" xml:space="preserve">
|
<trans-unit id="User selection" xml:space="preserve">
|
||||||
<source>User selection</source>
|
<source>User selection</source>
|
||||||
<target>用户选择</target>
|
<target>用户选择</target>
|
||||||
@@ -7499,11 +7579,6 @@ To connect, please ask your contact to create another connection link and check
|
|||||||
<target>XFTP 服务器</target>
|
<target>XFTP 服务器</target>
|
||||||
<note>No comment provided by engineer.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="You" xml:space="preserve">
|
|
||||||
<source>You</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">
|
<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>
|
<source>You **must not** use the same database on two devices.</source>
|
||||||
<target>您 **不得** 在两台设备上使用相同的数据库。</target>
|
<target>您 **不得** 在两台设备上使用相同的数据库。</target>
|
||||||
|
|||||||
@@ -26,14 +26,52 @@ enum NSENotification {
|
|||||||
case nse(UNMutableNotificationContent)
|
case nse(UNMutableNotificationContent)
|
||||||
case callkit(RcvCallInvitation)
|
case callkit(RcvCallInvitation)
|
||||||
case empty
|
case empty
|
||||||
case msgInfo(NtfMsgInfo)
|
}
|
||||||
|
|
||||||
var isCallInvitation: Bool {
|
public enum NSENotificationData {
|
||||||
|
case connectionEvent(_ user: User, _ connEntity: ConnectionEntity)
|
||||||
|
case contactConnected(_ user: any UserLike, _ contact: Contact)
|
||||||
|
case contactRequest(_ user: any UserLike, _ contactRequest: UserContactRequest)
|
||||||
|
case messageReceived(_ user: any UserLike, _ cInfo: ChatInfo, _ cItem: ChatItem)
|
||||||
|
case callInvitation(_ invitation: RcvCallInvitation)
|
||||||
|
case msgInfo(NtfMsgAckInfo)
|
||||||
|
case noNtf
|
||||||
|
|
||||||
|
var callInvitation: RcvCallInvitation? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .nse(ntf): ntf.categoryIdentifier == ntfCategoryCallInvitation
|
case let .callInvitation(invitation): invitation
|
||||||
case .callkit: true
|
default: nil
|
||||||
case .empty: false
|
}
|
||||||
case .msgInfo: false
|
}
|
||||||
|
|
||||||
|
func notificationContent(_ badgeCount: Int) -> UNMutableNotificationContent {
|
||||||
|
return switch self {
|
||||||
|
case let .connectionEvent(user, connEntity): createConnectionEventNtf(user, connEntity, badgeCount)
|
||||||
|
case let .contactConnected(user, contact): createContactConnectedNtf(user, contact, badgeCount)
|
||||||
|
case let .contactRequest(user, contactRequest): createContactRequestNtf(user, contactRequest, badgeCount)
|
||||||
|
case let .messageReceived(user, cInfo, cItem): createMessageReceivedNtf(user, cInfo, cItem, badgeCount)
|
||||||
|
case let .callInvitation(invitation): createCallInvitationNtf(invitation, badgeCount)
|
||||||
|
case .msgInfo: UNMutableNotificationContent()
|
||||||
|
case .noNtf: UNMutableNotificationContent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var notificationEvent: NSENotificationData? {
|
||||||
|
return switch self {
|
||||||
|
case .connectionEvent: self
|
||||||
|
case .contactConnected: self
|
||||||
|
case .contactRequest: self
|
||||||
|
case .messageReceived: self
|
||||||
|
case .callInvitation: self
|
||||||
|
case .msgInfo: nil
|
||||||
|
case .noNtf: nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var newMsgData: (any UserLike, ChatInfo)? {
|
||||||
|
return switch self {
|
||||||
|
case let .messageReceived(user, cInfo, _): (user, cInfo)
|
||||||
|
default: nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,9 +81,10 @@ enum NSENotification {
|
|||||||
// or when background notification is received.
|
// or when background notification is received.
|
||||||
class NSEThreads {
|
class NSEThreads {
|
||||||
static let shared = NSEThreads()
|
static let shared = NSEThreads()
|
||||||
private static let queue = DispatchQueue(label: "chat.simplex.app.SimpleX-NSE.notification-threads.lock")
|
static let queue = DispatchQueue(label: "chat.simplex.app.SimpleX-NSE.notification-threads.lock")
|
||||||
private var allThreads: Set<UUID> = []
|
private var allThreads: Set<UUID> = []
|
||||||
private var activeThreads: [(UUID, NotificationService)] = []
|
var activeThreads: [(UUID, NotificationService)] = []
|
||||||
|
var droppedNotifications: [(ChatId, NSENotificationData)] = []
|
||||||
|
|
||||||
func newThread() -> UUID {
|
func newThread() -> UUID {
|
||||||
NSEThreads.queue.sync {
|
NSEThreads.queue.sync {
|
||||||
@@ -64,22 +103,19 @@ class NSEThreads {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func processNotification(_ id: ChatId, _ ntf: NSENotification) async -> Void {
|
func processNotification(_ id: ChatId, _ ntf: NSENotificationData) async -> Void {
|
||||||
var waitTime: Int64 = 5_000_000000
|
if let (_, nse) = rcvEntityThread(id),
|
||||||
while waitTime > 0 {
|
nse.expectedMessages[id]?.shouldProcessNtf ?? false {
|
||||||
if let (_, nse) = rcvEntityThread(id),
|
nse.processReceivedNtf(id, ntf, signalReady: true)
|
||||||
nse.shouldProcessNtf && nse.processReceivedNtf(ntf) {
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
try? await Task.sleep(nanoseconds: 10_000000)
|
|
||||||
waitTime -= 10_000000
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func rcvEntityThread(_ id: ChatId) -> (UUID, NotificationService)? {
|
private func rcvEntityThread(_ id: ChatId) -> (UUID, NotificationService)? {
|
||||||
NSEThreads.queue.sync {
|
NSEThreads.queue.sync {
|
||||||
activeThreads.first(where: { (_, nse) in nse.receiveEntityId == id })
|
// this selects the earliest thread that:
|
||||||
|
// 1) has this connection in nse.expectedMessages
|
||||||
|
// 2) has not completed processing messages for this connection (not ready)
|
||||||
|
activeThreads.first(where: { (_, nse) in nse.expectedMessages[id]?.ready == false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,29 +142,38 @@ class NSEThreads {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ExpectedMessage {
|
||||||
|
var ntfConn: UserNtfConn
|
||||||
|
var receiveConnId: String?
|
||||||
|
var expectedMsgId: String?
|
||||||
|
var allowedGetNextAttempts: Int
|
||||||
|
var msgBestAttemptNtf: NSENotificationData?
|
||||||
|
var ready: Bool
|
||||||
|
var shouldProcessNtf: Bool
|
||||||
|
var startedProcessingNewMsgs: Bool
|
||||||
|
var semaphore: DispatchSemaphore
|
||||||
|
}
|
||||||
|
|
||||||
// Notification service extension creates a new instance of the class and calls didReceive for each notification.
|
// Notification service extension creates a new instance of the class and calls didReceive for each notification.
|
||||||
// Each didReceive is called in its own thread, but multiple calls can be made in one process, and, empirically, there is never
|
// Each didReceive is called in its own thread, but multiple calls can be made in one process, and, empirically, there is never
|
||||||
// more than one process of notification service extension exists at a time.
|
// more than one process of notification service extension exists at a time.
|
||||||
// Soon after notification service delivers the last notification it is either suspended or terminated.
|
// Soon after notification service delivers the last notification it is either suspended or terminated.
|
||||||
class NotificationService: UNNotificationServiceExtension {
|
class NotificationService: UNNotificationServiceExtension {
|
||||||
var contentHandler: ((UNNotificationContent) -> Void)?
|
var contentHandler: ((UNNotificationContent) -> Void)?
|
||||||
var bestAttemptNtf: NSENotification?
|
// served as notification if no message attempts (msgBestAttemptNtf) could be produced
|
||||||
|
var serviceBestAttemptNtf: NSENotification?
|
||||||
var badgeCount: Int = 0
|
var badgeCount: Int = 0
|
||||||
// thread is added to allThreads here - if thread did not start chat,
|
// thread is added to allThreads here - if thread did not start chat,
|
||||||
// chat does not need to be suspended but NSE state still needs to be set to "suspended".
|
// chat does not need to be suspended but NSE state still needs to be set to "suspended".
|
||||||
var threadId: UUID? = NSEThreads.shared.newThread()
|
var threadId: UUID? = NSEThreads.shared.newThread()
|
||||||
var notificationInfo: NtfMessages?
|
var expectedMessages: Dictionary<String, ExpectedMessage> = [:] // key is receiveEntityId
|
||||||
var receiveEntityId: String?
|
|
||||||
var expectedMessage: String?
|
|
||||||
// return true if the message is taken - it prevents sending it to another NotificationService instance for processing
|
|
||||||
var shouldProcessNtf = false
|
|
||||||
var appSubscriber: AppSubscriber?
|
var appSubscriber: AppSubscriber?
|
||||||
var returnedSuspension = false
|
var returnedSuspension = false
|
||||||
|
|
||||||
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
|
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
|
||||||
logger.debug("DEBUGGING: NotificationService.didReceive")
|
logger.debug("DEBUGGING: NotificationService.didReceive")
|
||||||
let ntf = if let ntf_ = request.content.mutableCopy() as? UNMutableNotificationContent { ntf_ } else { UNMutableNotificationContent() }
|
let ntf = if let ntf_ = request.content.mutableCopy() as? UNMutableNotificationContent { ntf_ } else { UNMutableNotificationContent() }
|
||||||
setBestAttemptNtf(ntf)
|
setServiceBestAttemptNtf(ntf)
|
||||||
self.contentHandler = contentHandler
|
self.contentHandler = contentHandler
|
||||||
registerGroupDefaults()
|
registerGroupDefaults()
|
||||||
let appState = appStateGroupDefault.get()
|
let appState = appStateGroupDefault.get()
|
||||||
@@ -136,13 +181,11 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
switch appState {
|
switch appState {
|
||||||
case .stopped:
|
case .stopped:
|
||||||
setBadgeCount()
|
setBadgeCount()
|
||||||
setBestAttemptNtf(createAppStoppedNtf())
|
setServiceBestAttemptNtf(createAppStoppedNtf(badgeCount))
|
||||||
deliverBestAttemptNtf()
|
deliverBestAttemptNtf()
|
||||||
case .suspended:
|
case .suspended:
|
||||||
setBadgeCount()
|
|
||||||
receiveNtfMessages(request, contentHandler)
|
receiveNtfMessages(request, contentHandler)
|
||||||
case .suspending:
|
case .suspending:
|
||||||
setBadgeCount()
|
|
||||||
Task {
|
Task {
|
||||||
let state: AppState = await withCheckedContinuation { cont in
|
let state: AppState = await withCheckedContinuation { cont in
|
||||||
appSubscriber = appStateSubscriber { s in
|
appSubscriber = appStateSubscriber { s in
|
||||||
@@ -169,8 +212,9 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
deliverBestAttemptNtf()
|
deliverBestAttemptNtf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
case .active: contentHandler(UNMutableNotificationContent())
|
||||||
deliverBestAttemptNtf()
|
case .activating: contentHandler(UNMutableNotificationContent())
|
||||||
|
case .bgRefresh: contentHandler(UNMutableNotificationContent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,62 +234,165 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
if let t = threadId { NSEThreads.shared.startThread(t, self) }
|
if let t = threadId { NSEThreads.shared.startThread(t, self) }
|
||||||
let dbStatus = startChat()
|
let dbStatus = startChat()
|
||||||
if case .ok = dbStatus,
|
if case .ok = dbStatus,
|
||||||
let ntfInfo = apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo) {
|
let ntfConns = apiGetNtfConns(nonce: nonce, encNtfInfo: encNtfInfo) {
|
||||||
logger.debug("NotificationService: receiveNtfMessages: apiGetNtfMessage \(String(describing: ntfInfo.ntfMessage_ == nil ? 0 : 1))")
|
logger.debug("NotificationService: receiveNtfMessages: apiGetNtfConns ntfConns count = \(ntfConns.count)")
|
||||||
if let connEntity = ntfInfo.connEntity_ {
|
|
||||||
setBestAttemptNtf(
|
for ntfConn in ntfConns {
|
||||||
ntfInfo.ntfsEnabled
|
addExpectedMessage(ntfConn: ntfConn)
|
||||||
? .nse(createConnectionEventNtf(ntfInfo.user, connEntity))
|
}
|
||||||
: .empty
|
|
||||||
)
|
let connIdsToGet = expectedMessages.compactMap { (id, _) in
|
||||||
if let id = connEntity.id, ntfInfo.msgTs != nil {
|
let started = NSEThreads.queue.sync {
|
||||||
notificationInfo = ntfInfo
|
let canStart = checkCanStart(id)
|
||||||
receiveEntityId = id
|
if let t = threadId { logger.debug("NotificationService thread \(t, privacy: .private): receiveNtfMessages: can start: \(canStart)") }
|
||||||
expectedMessage = ntfInfo.ntfMessage_.flatMap { $0.msgId }
|
if canStart {
|
||||||
shouldProcessNtf = true
|
processDroppedNotifications(id)
|
||||||
return
|
expectedMessages[id]?.startedProcessingNewMsgs = true
|
||||||
|
expectedMessages[id]?.shouldProcessNtf = true
|
||||||
|
}
|
||||||
|
return canStart
|
||||||
|
}
|
||||||
|
if started {
|
||||||
|
return expectedMessages[id]?.receiveConnId
|
||||||
|
} else {
|
||||||
|
if let t = threadId { logger.debug("NotificationService thread \(t, privacy: .private): receiveNtfMessages: entity \(id, privacy: .private) waiting on semaphore") }
|
||||||
|
expectedMessages[id]?.semaphore.wait()
|
||||||
|
if let t = threadId { logger.debug("NotificationService thread \(t, privacy: .private): receiveNtfMessages: entity \(id, privacy: .private) proceeding after semaphore") }
|
||||||
|
Task {
|
||||||
|
NSEThreads.queue.sync {
|
||||||
|
processDroppedNotifications(id)
|
||||||
|
expectedMessages[id]?.startedProcessingNewMsgs = true
|
||||||
|
expectedMessages[id]?.shouldProcessNtf = true
|
||||||
|
}
|
||||||
|
if let connId = expectedMessages[id]?.receiveConnId {
|
||||||
|
let _ = getConnNtfMessage(connId: connId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !connIdsToGet.isEmpty {
|
||||||
|
if let r = apiGetConnNtfMessages(connIds: connIdsToGet) {
|
||||||
|
logger.debug("NotificationService: receiveNtfMessages: apiGetConnNtfMessages count = \(r.count)")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
} else if let dbStatus = dbStatus {
|
} else if let dbStatus = dbStatus {
|
||||||
setBestAttemptNtf(createErrorNtf(dbStatus))
|
setServiceBestAttemptNtf(createErrorNtf(dbStatus, badgeCount))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
deliverBestAttemptNtf()
|
deliverBestAttemptNtf()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addExpectedMessage(ntfConn: UserNtfConn) {
|
||||||
|
if let connEntity = ntfConn.connEntity_,
|
||||||
|
let receiveEntityId = connEntity.id, ntfConn.expectedMsg_ != nil {
|
||||||
|
let expectedMsgId = ntfConn.expectedMsg_?.msgId
|
||||||
|
logger.debug("NotificationService: addExpectedMessage: expectedMsgId = \(expectedMsgId ?? "nil", privacy: .private)")
|
||||||
|
expectedMessages[receiveEntityId] = ExpectedMessage(
|
||||||
|
ntfConn: ntfConn,
|
||||||
|
receiveConnId: connEntity.conn.agentConnId,
|
||||||
|
expectedMsgId: expectedMsgId,
|
||||||
|
allowedGetNextAttempts: 3,
|
||||||
|
msgBestAttemptNtf: ntfConn.defaultBestAttemptNtf,
|
||||||
|
ready: false,
|
||||||
|
shouldProcessNtf: false,
|
||||||
|
startedProcessingNewMsgs: false,
|
||||||
|
semaphore: DispatchSemaphore(value: 0)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkCanStart(_ entityId: String) -> Bool {
|
||||||
|
return !NSEThreads.shared.activeThreads.contains(where: {
|
||||||
|
(tId, nse) in tId != threadId && nse.expectedMessages.contains(where: { $0.key == entityId })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func processDroppedNotifications(_ entityId: String) {
|
||||||
|
if !NSEThreads.shared.droppedNotifications.isEmpty {
|
||||||
|
let messagesToProcess = NSEThreads.shared.droppedNotifications.filter { (eId, _) in eId == entityId }
|
||||||
|
NSEThreads.shared.droppedNotifications.removeAll(where: { (eId, _) in eId == entityId })
|
||||||
|
for (index, (_, ntf)) in messagesToProcess.enumerated() {
|
||||||
|
if let t = threadId { logger.debug("NotificationService thread \(t, privacy: .private): entity \(entityId, privacy: .private): processing dropped notification \(index, privacy: .private)") }
|
||||||
|
processReceivedNtf(entityId, ntf, signalReady: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override func serviceExtensionTimeWillExpire() {
|
override func serviceExtensionTimeWillExpire() {
|
||||||
logger.debug("DEBUGGING: NotificationService.serviceExtensionTimeWillExpire")
|
logger.debug("DEBUGGING: NotificationService.serviceExtensionTimeWillExpire")
|
||||||
deliverBestAttemptNtf(urgent: true)
|
deliverBestAttemptNtf(urgent: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func processReceivedNtf(_ ntf: NSENotification) -> Bool {
|
var expectingMoreMessages: Bool {
|
||||||
guard let ntfInfo = notificationInfo, let msgTs = ntfInfo.msgTs else { return false }
|
!expectedMessages.allSatisfy { $0.value.ready }
|
||||||
if !ntfInfo.user.showNotifications {
|
}
|
||||||
self.setBestAttemptNtf(.empty)
|
|
||||||
|
func processReceivedNtf(_ id: ChatId, _ ntf: NSENotificationData, signalReady: Bool) {
|
||||||
|
guard let expectedMessage = expectedMessages[id] else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let expectedMsgTs = expectedMessage.ntfConn.expectedMsg_?.msgTs else {
|
||||||
|
NSEThreads.shared.droppedNotifications.append((id, ntf))
|
||||||
|
if signalReady { entityReady(id) }
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if case let .msgInfo(info) = ntf {
|
if case let .msgInfo(info) = ntf {
|
||||||
if info.msgId == expectedMessage {
|
if info.msgId == expectedMessage.expectedMsgId {
|
||||||
expectedMessage = nil
|
logger.debug("NotificationService processNtf: msgInfo msgId = \(info.msgId, privacy: .private): expected")
|
||||||
logger.debug("NotificationService processNtf: msgInfo")
|
expectedMessages[id]?.expectedMsgId = nil
|
||||||
|
if signalReady { entityReady(id) }
|
||||||
self.deliverBestAttemptNtf()
|
self.deliverBestAttemptNtf()
|
||||||
return true
|
} else if let msgTs = info.msgTs_, msgTs > expectedMsgTs {
|
||||||
} else if info.msgTs > msgTs {
|
logger.debug("NotificationService processNtf: msgInfo msgId = \(info.msgId, privacy: .private): unexpected msgInfo, let other instance to process it, stopping this one")
|
||||||
logger.debug("NotificationService processNtf: unexpected msgInfo, let other instance to process it, stopping this one")
|
NSEThreads.shared.droppedNotifications.append((id, ntf))
|
||||||
|
if signalReady { entityReady(id) }
|
||||||
self.deliverBestAttemptNtf()
|
self.deliverBestAttemptNtf()
|
||||||
return false
|
} else if (expectedMessages[id]?.allowedGetNextAttempts ?? 0) > 0, let receiveConnId = expectedMessages[id]?.receiveConnId {
|
||||||
|
logger.debug("NotificationService processNtf: msgInfo msgId = \(info.msgId, privacy: .private): unexpected msgInfo, get next message")
|
||||||
|
expectedMessages[id]?.allowedGetNextAttempts -= 1
|
||||||
|
if let receivedMsg = getConnNtfMessage(connId: receiveConnId) {
|
||||||
|
logger.debug("NotificationService processNtf, on getConnNtfMessage: msgInfo msgId = \(info.msgId, privacy: .private), receivedMsg msgId = \(receivedMsg.msgId, privacy: .private)")
|
||||||
|
} else {
|
||||||
|
logger.debug("NotificationService processNtf, on getConnNtfMessage: msgInfo msgId = \(info.msgId, privacy: .private): no next message, deliver best attempt")
|
||||||
|
NSEThreads.shared.droppedNotifications.append((id, ntf))
|
||||||
|
if signalReady { entityReady(id) }
|
||||||
|
self.deliverBestAttemptNtf()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.debug("NotificationService processNtf: unknown message, let other instance to process it")
|
logger.debug("NotificationService processNtf: msgInfo msgId = \(info.msgId, privacy: .private): unknown message, let other instance to process it")
|
||||||
return false
|
NSEThreads.shared.droppedNotifications.append((id, ntf))
|
||||||
}
|
if signalReady { entityReady(id) }
|
||||||
} else if ntfInfo.user.showNotifications {
|
|
||||||
logger.debug("NotificationService processNtf: setting best attempt")
|
|
||||||
self.setBestAttemptNtf(ntf)
|
|
||||||
if ntf.isCallInvitation {
|
|
||||||
self.deliverBestAttemptNtf()
|
self.deliverBestAttemptNtf()
|
||||||
}
|
}
|
||||||
return true
|
} else if expectedMessage.ntfConn.user.showNotifications {
|
||||||
|
logger.debug("NotificationService processNtf: setting best attempt")
|
||||||
|
if ntf.notificationEvent != nil {
|
||||||
|
setBadgeCount()
|
||||||
|
}
|
||||||
|
let prevBestAttempt = expectedMessages[id]?.msgBestAttemptNtf
|
||||||
|
if prevBestAttempt?.callInvitation != nil {
|
||||||
|
if ntf.callInvitation != nil { // replace with newer call
|
||||||
|
expectedMessages[id]?.msgBestAttemptNtf = ntf
|
||||||
|
} // otherwise keep call as best attempt
|
||||||
|
} else {
|
||||||
|
expectedMessages[id]?.msgBestAttemptNtf = ntf
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NSEThreads.shared.droppedNotifications.append((id, ntf))
|
||||||
|
if signalReady { entityReady(id) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func entityReady(_ entityId: ChatId) {
|
||||||
|
if let t = threadId { logger.debug("NotificationService thread \(t, privacy: .private): entityReady: entity \(entityId, privacy: .private)") }
|
||||||
|
expectedMessages[entityId]?.ready = true
|
||||||
|
if let (tNext, nse) = NSEThreads.shared.activeThreads.first(where: { (_, nse) in nse.expectedMessages[entityId]?.startedProcessingNewMsgs == false }) {
|
||||||
|
if let t = threadId { logger.debug("NotificationService thread \(t, privacy: .private): entityReady: signal next thread \(tNext, privacy: .private) for entity \(entityId, privacy: .private)") }
|
||||||
|
nse.expectedMessages[entityId]?.semaphore.signal()
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setBadgeCount() {
|
func setBadgeCount() {
|
||||||
@@ -253,37 +400,32 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
ntfBadgeCountGroupDefault.set(badgeCount)
|
ntfBadgeCountGroupDefault.set(badgeCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setBestAttemptNtf(_ ntf: UNMutableNotificationContent) {
|
func setServiceBestAttemptNtf(_ ntf: UNMutableNotificationContent) {
|
||||||
setBestAttemptNtf(.nse(ntf))
|
logger.debug("NotificationService.setServiceBestAttemptNtf")
|
||||||
}
|
serviceBestAttemptNtf = .nse(ntf)
|
||||||
|
|
||||||
func setBestAttemptNtf(_ ntf: NSENotification) {
|
|
||||||
logger.debug("NotificationService.setBestAttemptNtf")
|
|
||||||
if case let .nse(notification) = ntf {
|
|
||||||
notification.badge = badgeCount as NSNumber
|
|
||||||
bestAttemptNtf = .nse(notification)
|
|
||||||
} else {
|
|
||||||
bestAttemptNtf = ntf
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func deliverBestAttemptNtf(urgent: Bool = false) {
|
private func deliverBestAttemptNtf(urgent: Bool = false) {
|
||||||
logger.debug("NotificationService.deliverBestAttemptNtf")
|
if (urgent || !expectingMoreMessages) {
|
||||||
// stop processing other messages
|
logger.debug("NotificationService.deliverBestAttemptNtf")
|
||||||
shouldProcessNtf = false
|
// stop processing other messages
|
||||||
|
for (key, _) in expectedMessages {
|
||||||
|
expectedMessages[key]?.shouldProcessNtf = false
|
||||||
|
}
|
||||||
|
|
||||||
let suspend: Bool
|
let suspend: Bool
|
||||||
if let t = threadId {
|
if let t = threadId {
|
||||||
threadId = nil
|
threadId = nil
|
||||||
suspend = NSEThreads.shared.endThread(t) && NSEThreads.shared.noThreads
|
suspend = NSEThreads.shared.endThread(t) && NSEThreads.shared.noThreads
|
||||||
} else {
|
} else {
|
||||||
suspend = false
|
suspend = false
|
||||||
|
}
|
||||||
|
deliverCallkitOrNotification(urgent: urgent, suspend: suspend)
|
||||||
}
|
}
|
||||||
deliverCallkitOrNotification(urgent: urgent, suspend: suspend)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func deliverCallkitOrNotification(urgent: Bool, suspend: Bool = false) {
|
private func deliverCallkitOrNotification(urgent: Bool, suspend: Bool = false) {
|
||||||
if case .callkit = bestAttemptNtf {
|
if useCallKit() && expectedMessages.contains(where: { $0.value.msgBestAttemptNtf?.callInvitation != nil }) {
|
||||||
logger.debug("NotificationService.deliverCallkitOrNotification: will suspend, callkit")
|
logger.debug("NotificationService.deliverCallkitOrNotification: will suspend, callkit")
|
||||||
if urgent {
|
if urgent {
|
||||||
// suspending NSE even though there may be other notifications
|
// suspending NSE even though there may be other notifications
|
||||||
@@ -321,19 +463,13 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func deliverNotification() {
|
private func deliverNotification() {
|
||||||
if let handler = contentHandler, let ntf = bestAttemptNtf {
|
if let handler = contentHandler, let ntf = prepareNotification() {
|
||||||
contentHandler = nil
|
contentHandler = nil
|
||||||
bestAttemptNtf = nil
|
serviceBestAttemptNtf = nil
|
||||||
let deliver: (UNMutableNotificationContent?) -> Void = { ntf in
|
|
||||||
let useNtf = if let ntf = ntf {
|
|
||||||
appStateGroupDefault.get().running ? UNMutableNotificationContent() : ntf
|
|
||||||
} else {
|
|
||||||
UNMutableNotificationContent()
|
|
||||||
}
|
|
||||||
handler(useNtf)
|
|
||||||
}
|
|
||||||
switch ntf {
|
switch ntf {
|
||||||
case let .nse(content): deliver(content)
|
case let .nse(content):
|
||||||
|
content.badge = badgeCount as NSNumber
|
||||||
|
handler(content)
|
||||||
case let .callkit(invitation):
|
case let .callkit(invitation):
|
||||||
logger.debug("NotificationService reportNewIncomingVoIPPushPayload for \(invitation.contact.id)")
|
logger.debug("NotificationService reportNewIncomingVoIPPushPayload for \(invitation.contact.id)")
|
||||||
CXProvider.reportNewIncomingVoIPPushPayload([
|
CXProvider.reportNewIncomingVoIPPushPayload([
|
||||||
@@ -344,13 +480,85 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
"callTs": invitation.callTs.timeIntervalSince1970
|
"callTs": invitation.callTs.timeIntervalSince1970
|
||||||
]) { error in
|
]) { error in
|
||||||
logger.debug("reportNewIncomingVoIPPushPayload result: \(error)")
|
logger.debug("reportNewIncomingVoIPPushPayload result: \(error)")
|
||||||
deliver(error == nil ? nil : createCallInvitationNtf(invitation))
|
handler(error == nil ? UNMutableNotificationContent() : createCallInvitationNtf(invitation, self.badgeCount))
|
||||||
}
|
}
|
||||||
case .empty: deliver(nil) // used to mute notifications that did not unsubscribe yet
|
case .empty:
|
||||||
case .msgInfo: deliver(nil) // unreachable, the best attempt is never set to msgInfo
|
handler(UNMutableNotificationContent()) // used to mute notifications that did not unsubscribe yet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func prepareNotification() -> NSENotification? {
|
||||||
|
if expectedMessages.isEmpty {
|
||||||
|
return serviceBestAttemptNtf
|
||||||
|
} else if let callNtfKV = expectedMessages.first(where: { $0.value.msgBestAttemptNtf?.callInvitation != nil }),
|
||||||
|
let callInv = callNtfKV.value.msgBestAttemptNtf?.callInvitation,
|
||||||
|
let callNtf = callNtfKV.value.msgBestAttemptNtf {
|
||||||
|
return useCallKit() ? .callkit(callInv) : .nse(callNtf.notificationContent(badgeCount))
|
||||||
|
} else {
|
||||||
|
let ntfEvents = expectedMessages.compactMap { $0.value.msgBestAttemptNtf?.notificationEvent }
|
||||||
|
if ntfEvents.isEmpty {
|
||||||
|
return .empty
|
||||||
|
} else if let ntfEvent = ntfEvents.count == 1 ? ntfEvents.first : nil {
|
||||||
|
return .nse(ntfEvent.notificationContent(badgeCount))
|
||||||
|
} else {
|
||||||
|
return .nse(createJointNtf(ntfEvents))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func createJointNtf(_ ntfEvents: [NSENotificationData]) -> UNMutableNotificationContent {
|
||||||
|
let previewMode = ntfPreviewModeGroupDefault.get()
|
||||||
|
let newMsgsData: [(any UserLike, ChatInfo)] = ntfEvents.compactMap { $0.newMsgData }
|
||||||
|
if !newMsgsData.isEmpty, let userId = newMsgsData.first?.0.userId {
|
||||||
|
let newMsgsChats: [ChatInfo] = newMsgsData.map { $0.1 }
|
||||||
|
let uniqueChatsNames = uniqueNewMsgsChatsNames(newMsgsChats)
|
||||||
|
var body: String
|
||||||
|
if previewMode == .hidden {
|
||||||
|
body = String.localizedStringWithFormat(NSLocalizedString("New messages in %d chats", comment: "notification body"), uniqueChatsNames.count)
|
||||||
|
} else {
|
||||||
|
body = String.localizedStringWithFormat(NSLocalizedString("From: %@", comment: "notification body"), newMsgsChatsNamesStr(uniqueChatsNames))
|
||||||
|
}
|
||||||
|
return createNotification(
|
||||||
|
categoryIdentifier: ntfCategoryManyEvents,
|
||||||
|
title: NSLocalizedString("New messages", comment: "notification"),
|
||||||
|
body: body,
|
||||||
|
userInfo: ["userId": userId],
|
||||||
|
badgeCount: badgeCount
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return createNotification(
|
||||||
|
categoryIdentifier: ntfCategoryManyEvents,
|
||||||
|
title: NSLocalizedString("New events", comment: "notification"),
|
||||||
|
body: String.localizedStringWithFormat(NSLocalizedString("%d new events", comment: "notification body"), ntfEvents.count),
|
||||||
|
badgeCount: badgeCount
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func uniqueNewMsgsChatsNames(_ newMsgsChats: [ChatInfo]) -> [String] {
|
||||||
|
var seenChatIds = Set<ChatId>()
|
||||||
|
var uniqueChatsNames: [String] = []
|
||||||
|
for chat in newMsgsChats {
|
||||||
|
if !seenChatIds.contains(chat.id) {
|
||||||
|
seenChatIds.insert(chat.id)
|
||||||
|
uniqueChatsNames.append(chat.chatViewName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uniqueChatsNames
|
||||||
|
}
|
||||||
|
|
||||||
|
private func newMsgsChatsNamesStr(_ names: [String]) -> String {
|
||||||
|
return switch names.count {
|
||||||
|
case 1: names[0]
|
||||||
|
case 2: "\(names[0]) and \(names[1])"
|
||||||
|
case 3: "\(names[0] + ", " + names[1]) and \(names[2])"
|
||||||
|
default:
|
||||||
|
names.count > 3
|
||||||
|
? "\(names[0]), \(names[1]) and \(names.count - 2) other chats"
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// nseStateGroupDefault must not be used in NSE directly, only via this singleton
|
// nseStateGroupDefault must not be used in NSE directly, only via this singleton
|
||||||
@@ -564,28 +772,25 @@ func chatRecvMsg() async -> ChatResponse? {
|
|||||||
private let isInChina = SKStorefront().countryCode == "CHN"
|
private let isInChina = SKStorefront().countryCode == "CHN"
|
||||||
private func useCallKit() -> Bool { !isInChina && callKitEnabledGroupDefault.get() }
|
private func useCallKit() -> Bool { !isInChina && callKitEnabledGroupDefault.get() }
|
||||||
|
|
||||||
func receivedMsgNtf(_ res: ChatResponse) async -> (String, NSENotification)? {
|
func receivedMsgNtf(_ res: ChatResponse) async -> (String, NSENotificationData)? {
|
||||||
logger.debug("NotificationService receivedMsgNtf: \(res.responseType)")
|
logger.debug("NotificationService receivedMsgNtf: \(res.responseType)")
|
||||||
switch res {
|
switch res {
|
||||||
case let .contactConnected(user, contact, _):
|
case let .contactConnected(user, contact, _):
|
||||||
return (contact.id, .nse(createContactConnectedNtf(user, contact)))
|
return (contact.id, .contactConnected(user, contact))
|
||||||
// case let .contactConnecting(contact):
|
// case let .contactConnecting(contact):
|
||||||
// TODO profile update
|
// TODO profile update
|
||||||
case let .receivedContactRequest(user, contactRequest):
|
case let .receivedContactRequest(user, contactRequest):
|
||||||
return (UserContact(contactRequest: contactRequest).id, .nse(createContactRequestNtf(user, contactRequest)))
|
return (UserContact(contactRequest: contactRequest).id, .contactRequest(user, contactRequest))
|
||||||
case let .newChatItems(user, chatItems):
|
case let .newChatItems(user, chatItems):
|
||||||
// Received items are created one at a time
|
// Received items are created one at a time
|
||||||
if let chatItem = chatItems.first {
|
if let chatItem = chatItems.first {
|
||||||
let cInfo = chatItem.chatInfo
|
let cInfo = chatItem.chatInfo
|
||||||
var cItem = chatItem.chatItem
|
var cItem = chatItem.chatItem
|
||||||
if !cInfo.ntfsEnabled {
|
|
||||||
ntfBadgeCountGroupDefault.set(max(0, ntfBadgeCountGroupDefault.get() - 1))
|
|
||||||
}
|
|
||||||
if let file = cItem.autoReceiveFile() {
|
if let file = cItem.autoReceiveFile() {
|
||||||
cItem = autoReceiveFile(file) ?? cItem
|
cItem = autoReceiveFile(file) ?? cItem
|
||||||
}
|
}
|
||||||
let ntf: NSENotification = cInfo.ntfsEnabled ? .nse(createMessageReceivedNtf(user, cInfo, cItem)) : .empty
|
let ntf: NSENotificationData = (cInfo.ntfsEnabled && cItem.showNotification) ? .messageReceived(user, cInfo, cItem) : .noNtf
|
||||||
return cItem.showNotification ? (chatItem.chatId, ntf) : nil
|
return (chatItem.chatId, ntf)
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -602,10 +807,7 @@ func receivedMsgNtf(_ res: ChatResponse) async -> (String, NSENotification)? {
|
|||||||
return nil
|
return nil
|
||||||
case let .callInvitation(invitation):
|
case let .callInvitation(invitation):
|
||||||
// Do not post it without CallKit support, iOS will stop launching the app without showing CallKit
|
// Do not post it without CallKit support, iOS will stop launching the app without showing CallKit
|
||||||
return (
|
return (invitation.contact.id, .callInvitation(invitation))
|
||||||
invitation.contact.id,
|
|
||||||
useCallKit() ? .callkit(invitation) : .nse(createCallInvitationNtf(invitation))
|
|
||||||
)
|
|
||||||
case let .ntfMessage(_, connEntity, ntfMessage):
|
case let .ntfMessage(_, connEntity, ntfMessage):
|
||||||
return if let id = connEntity.id { (id, .msgInfo(ntfMessage)) } else { nil }
|
return if let id = connEntity.id { (id, .msgInfo(ntfMessage)) } else { nil }
|
||||||
case .chatSuspended:
|
case .chatSuspended:
|
||||||
@@ -686,15 +888,15 @@ func apiSetEncryptLocalFiles(_ enable: Bool) throws {
|
|||||||
throw r
|
throw r
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiGetNtfMessage(nonce: String, encNtfInfo: String) -> NtfMessages? {
|
func apiGetNtfConns(nonce: String, encNtfInfo: String) -> [UserNtfConn]? {
|
||||||
guard apiGetActiveUser() != nil else {
|
guard apiGetActiveUser() != nil else {
|
||||||
logger.debug("no active user")
|
logger.debug("no active user")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
let r = sendSimpleXCmd(.apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo))
|
let r = sendSimpleXCmd(.apiGetNtfConns(nonce: nonce, encNtfInfo: encNtfInfo))
|
||||||
if case let .ntfMessages(user, connEntity_, msgTs, ntfMessage_) = r, let user = user {
|
if case let .ntfConns(ntfConns) = r {
|
||||||
logger.debug("apiGetNtfMessage response ntfMessages: \(ntfMessage_ == nil ? 0 : 1)")
|
logger.debug("apiGetNtfConns response ntfConns: \(ntfConns.count)")
|
||||||
return NtfMessages(user: user, connEntity_: connEntity_, msgTs: msgTs, ntfMessage_: ntfMessage_)
|
return ntfConns.compactMap { toUserNtfConn($0) }
|
||||||
} else if case let .chatCmdError(_, error) = r {
|
} else if case let .chatCmdError(_, error) = r {
|
||||||
logger.debug("apiGetNtfMessage error response: \(String.init(describing: error))")
|
logger.debug("apiGetNtfMessage error response: \(String.init(describing: error))")
|
||||||
} else {
|
} else {
|
||||||
@@ -703,6 +905,36 @@ func apiGetNtfMessage(nonce: String, encNtfInfo: String) -> NtfMessages? {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toUserNtfConn(_ ntfConn: NtfConn) -> UserNtfConn? {
|
||||||
|
if let user = ntfConn.user_ {
|
||||||
|
return UserNtfConn(user: user, connEntity_: ntfConn.connEntity_, expectedMsg_: ntfConn.expectedMsg_)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func apiGetConnNtfMessages(connIds: [String]) -> [NtfMsgInfo?]? {
|
||||||
|
guard apiGetActiveUser() != nil else {
|
||||||
|
logger.debug("no active user")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
let r = sendSimpleXCmd(.apiGetConnNtfMessages(connIds: connIds))
|
||||||
|
if case let .connNtfMessages(receivedMsgs) = r {
|
||||||
|
logger.debug("apiGetConnNtfMessages response receivedMsgs: \(receivedMsgs.count)")
|
||||||
|
return receivedMsgs
|
||||||
|
}
|
||||||
|
logger.debug("apiGetConnNtfMessages error: \(responseError(r))")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getConnNtfMessage(connId: String) -> NtfMsgInfo? {
|
||||||
|
let r_ = apiGetConnNtfMessages(connIds: [connId])
|
||||||
|
if let r = r_, let receivedMsg = r.count == 1 ? r.first : nil {
|
||||||
|
return receivedMsg
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func apiReceiveFile(fileId: Int64, encrypted: Bool, inline: Bool? = nil) -> AChatItem? {
|
func apiReceiveFile(fileId: Int64, encrypted: Bool, inline: Bool? = nil) -> AChatItem? {
|
||||||
let userApprovedRelays = !privacyAskToApproveRelaysGroupDefault.get()
|
let userApprovedRelays = !privacyAskToApproveRelaysGroupDefault.get()
|
||||||
let r = sendSimpleXCmd(.receiveFile(fileId: fileId, userApprovedRelays: userApprovedRelays, encrypted: encrypted, inline: inline))
|
let r = sendSimpleXCmd(.receiveFile(fileId: fileId, userApprovedRelays: userApprovedRelays, encrypted: encrypted, inline: inline))
|
||||||
@@ -737,13 +969,33 @@ func setNetworkConfig(_ cfg: NetCfg) throws {
|
|||||||
throw r
|
throw r
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NtfMessages {
|
struct UserNtfConn {
|
||||||
var user: User
|
var user: User
|
||||||
var connEntity_: ConnectionEntity?
|
var connEntity_: ConnectionEntity?
|
||||||
var msgTs: Date?
|
var expectedMsg_: NtfMsgInfo?
|
||||||
var ntfMessage_: NtfMsgInfo?
|
|
||||||
|
|
||||||
var ntfsEnabled: Bool {
|
var defaultBestAttemptNtf: NSENotificationData {
|
||||||
user.showNotifications && (connEntity_?.ntfsEnabled ?? false)
|
return if !user.showNotifications {
|
||||||
|
.noNtf
|
||||||
|
} else if let connEntity = connEntity_ {
|
||||||
|
switch connEntity {
|
||||||
|
case let .rcvDirectMsgConnection(_, contact):
|
||||||
|
contact?.chatSettings.enableNtfs == .all
|
||||||
|
? .connectionEvent(user, connEntity)
|
||||||
|
: .noNtf
|
||||||
|
case let .rcvGroupMsgConnection(_, groupInfo, _):
|
||||||
|
groupInfo.chatSettings.enableNtfs == .all
|
||||||
|
? .connectionEvent(user, connEntity)
|
||||||
|
: .noNtf
|
||||||
|
case .sndFileConnection: .noNtf
|
||||||
|
case .rcvFileConnection: .noNtf
|
||||||
|
case let .userContactConnection(_, userContact):
|
||||||
|
userContact.groupId == nil
|
||||||
|
? .connectionEvent(user, connEntity)
|
||||||
|
: .noNtf
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
.noNtf
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -417,7 +417,7 @@ fileprivate func getSharedContent(_ ip: NSItemProvider) async -> Result<SharedCo
|
|||||||
let data = try? Data(contentsOf: url),
|
let data = try? Data(contentsOf: url),
|
||||||
let image = UIImage(data: data),
|
let image = UIImage(data: data),
|
||||||
let cryptoFile = saveFile(data, generateNewFileName("IMG", "gif"), encrypted: privacyEncryptLocalFilesGroupDefault.get()),
|
let cryptoFile = saveFile(data, generateNewFileName("IMG", "gif"), encrypted: privacyEncryptLocalFilesGroupDefault.get()),
|
||||||
let preview = resizeImageToStrSize(image, maxDataSize: MAX_DATA_SIZE) {
|
let preview = await resizeImageToStrSize(image, maxDataSize: MAX_DATA_SIZE) {
|
||||||
.success(.image(preview: preview, cryptoFile: cryptoFile))
|
.success(.image(preview: preview, cryptoFile: cryptoFile))
|
||||||
} else { .failure(ErrorAlert("Error preparing message")) }
|
} else { .failure(ErrorAlert("Error preparing message")) }
|
||||||
|
|
||||||
@@ -425,7 +425,7 @@ fileprivate func getSharedContent(_ ip: NSItemProvider) async -> Result<SharedCo
|
|||||||
} else {
|
} else {
|
||||||
if let image = await staticImage(),
|
if let image = await staticImage(),
|
||||||
let cryptoFile = saveImage(image),
|
let cryptoFile = saveImage(image),
|
||||||
let preview = resizeImageToStrSize(image, maxDataSize: MAX_DATA_SIZE) {
|
let preview = await resizeImageToStrSize(image, maxDataSize: MAX_DATA_SIZE) {
|
||||||
.success(.image(preview: preview, cryptoFile: cryptoFile))
|
.success(.image(preview: preview, cryptoFile: cryptoFile))
|
||||||
} else { .failure(ErrorAlert("Error preparing message")) }
|
} else { .failure(ErrorAlert("Error preparing message")) }
|
||||||
}
|
}
|
||||||
@@ -435,7 +435,7 @@ fileprivate func getSharedContent(_ ip: NSItemProvider) async -> Result<SharedCo
|
|||||||
if let url = try? await inPlaceUrl(type: type),
|
if let url = try? await inPlaceUrl(type: type),
|
||||||
let trancodedUrl = await transcodeVideo(from: url),
|
let trancodedUrl = await transcodeVideo(from: url),
|
||||||
let (image, duration) = AVAsset(url: trancodedUrl).generatePreview(),
|
let (image, duration) = AVAsset(url: trancodedUrl).generatePreview(),
|
||||||
let preview = resizeImageToStrSize(image, maxDataSize: MAX_DATA_SIZE),
|
let preview = await resizeImageToStrSize(image, maxDataSize: MAX_DATA_SIZE),
|
||||||
let cryptoFile = moveTempFileFromURL(trancodedUrl) {
|
let cryptoFile = moveTempFileFromURL(trancodedUrl) {
|
||||||
try? FileManager.default.removeItem(at: trancodedUrl)
|
try? FileManager.default.removeItem(at: trancodedUrl)
|
||||||
return .success(.movie(preview: preview, duration: duration, cryptoFile: cryptoFile))
|
return .success(.movie(preview: preview, duration: duration, cryptoFile: cryptoFile))
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
"Database error" = "Error en base de datos";
|
"Database error" = "Error en base de datos";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Database passphrase is different from saved in the keychain." = "La contraseña de la base de datos es distinta a la almacenada en keychain.";
|
"Database passphrase is different from saved in the keychain." = "La contraseña de la base de datos es diferente a la almacenada en keychain.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Database passphrase is required to open chat." = "Se requiere la contraseña de la base de datos para abrir la aplicación.";
|
"Database passphrase is required to open chat." = "Se requiere la contraseña de la base de datos para abrir la aplicación.";
|
||||||
|
|||||||
@@ -26,13 +26,13 @@
|
|||||||
"Database encrypted!" = "Adatbázis titkosítva!";
|
"Database encrypted!" = "Adatbázis titkosítva!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Database error" = "Adatbázis hiba";
|
"Database error" = "Adatbázishiba";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Database passphrase is different from saved in the keychain." = "Az adatbázis jelmondata eltér a kulcstartóban lévőtől.";
|
"Database passphrase is different from saved in the keychain." = "Az adatbázis jelmondata eltér a kulcstartóban lévőtől.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Database passphrase is required to open chat." = "Adatbázis jelmondat szükséges a csevegés megnyitásához.";
|
"Database passphrase is required to open chat." = "Adatbázis-jelmondat szükséges a csevegés megnyitásához.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Database upgrade required" = "Adatbázis fejlesztése szükséges";
|
"Database upgrade required" = "Adatbázis fejlesztése szükséges";
|
||||||
@@ -50,13 +50,13 @@
|
|||||||
"File error" = "Fájlhiba";
|
"File error" = "Fájlhiba";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Incompatible database version" = "Nem kompatibilis adatbázis verzió";
|
"Incompatible database version" = "Nem kompatibilis adatbázis-verzió";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Invalid migration confirmation" = "Érvénytelen átköltöztetési visszaigazolás";
|
"Invalid migration confirmation" = "Érvénytelen átköltöztetési visszaigazolás";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Keychain error" = "Kulcstartó hiba";
|
"Keychain error" = "Kulcstartóhiba";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Large file!" = "Nagy fájl!";
|
"Large file!" = "Nagy fájl!";
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
"Slow network?" = "Lassú internetkapcsolat?";
|
"Slow network?" = "Lassú internetkapcsolat?";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Unknown database error: %@" = "Ismeretlen adatbázis hiba: %@";
|
"Unknown database error: %@" = "Ismeretlen adatbázishiba: %@";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Unsupported format" = "Nem támogatott formátum";
|
"Unsupported format" = "Nem támogatott formátum";
|
||||||
@@ -104,7 +104,7 @@
|
|||||||
"Wait" = "Várjon";
|
"Wait" = "Várjon";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Wrong database passphrase" = "Hibás adatbázis jelmondat";
|
"Wrong database passphrase" = "Hibás adatbázis-jelmondat";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "A megosztást az Adatvédelem és biztonság / SimpleX-zár menüben engedélyezheti.";
|
"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "A megosztást az Adatvédelem és biztonság / SimpleX-zár menüben engedélyezheti.";
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
/*
|
/* Bundle display name */
|
||||||
InfoPlist.strings
|
"CFBundleDisplayName" = "SimpleX SE";
|
||||||
SimpleX
|
|
||||||
|
/* Bundle name */
|
||||||
|
"CFBundleName" = "SimpleX SE";
|
||||||
|
|
||||||
|
/* Copyright (human-readable) */
|
||||||
|
"NSHumanReadableCopyright" = "Telif Hakkı © 2024 SimpleX Chat. Tüm hakları saklıdır.";
|
||||||
|
|
||||||
Created by EP on 30/07/2024.
|
|
||||||
Copyright © 2024 SimpleX Chat. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -1,7 +1,111 @@
|
|||||||
/*
|
/* No comment provided by engineer. */
|
||||||
Localizable.strings
|
"%@" = "%@";
|
||||||
SimpleX
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"App is locked!" = "Uygulama kilitlendi!";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Cancel" = "İptal et";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Cannot access keychain to save database password" = "Veritabanı şifresini kaydetmek için Anahtar Zinciri'ne erişilemiyor";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Cannot forward message" = "Mesaj iletilemiyor";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Comment" = "Yorum";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Currently maximum supported file size is %@." = "Şu anki maksimum desteklenen dosya boyutu %@ kadardır.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Database downgrade required" = "Veritabanı sürüm düşürme gerekli";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Database encrypted!" = "Veritabanı şifrelendi!";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Database error" = "Veritabanı hatası";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Database passphrase is different from saved in the keychain." = "Veritabanı parolası Anahtar Zinciri'nde kayıtlı olandan farklıdır.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Database passphrase is required to open chat." = "Konuşmayı açmak için veri tabanı parolası gerekli.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Database upgrade required" = "Veritabanı yükseltmesi gerekli";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Error preparing file" = "Dosya hazırlanırken hata oluştu";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Error preparing message" = "Mesaj hazırlanırken hata oluştu";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Error: %@" = "Hata: %@";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"File error" = "Dosya hatası";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Incompatible database version" = "Uyumsuz veritabanı sürümü";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Invalid migration confirmation" = "Geçerli olmayan taşıma onayı";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Keychain error" = "Anahtarlık hatası";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Large file!" = "Büyük dosya!";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"No active profile" = "Aktif profil yok";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Ok" = "Tamam";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Open the app to downgrade the database." = "Veritabanının sürümünü düşürmek için uygulamayı açın.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Open the app to upgrade the database." = "Veritabanını güncellemek için uygulamayı açın.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Passphrase" = "Parola";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Please create a profile in the SimpleX app" = "Lütfen SimpleX uygulamasında bir profil oluşturun";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Selected chat preferences prohibit this message." = "Seçilen sohbet tercihleri bu mesajı yasakladı.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Sending a message takes longer than expected." = "Mesaj göndermek beklenenden daha uzun sürüyor.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Sending message…" = "Mesaj gönderiliyor…";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Share" = "Paylaş";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Slow network?" = "Ağ yavaş mı?";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Unknown database error: %@" = "Bilinmeyen veritabanı hatası: %@";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Unsupported format" = "Desteklenmeyen format";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Wait" = "Bekleyin";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Wrong database passphrase" = "Yanlış veritabanı parolası";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "Gizlilik ve Güvenlik / SimpleX Lock ayarlarından paylaşıma izin verebilirsiniz.";
|
||||||
|
|
||||||
Created by EP on 30/07/2024.
|
|
||||||
Copyright © 2024 SimpleX Chat. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -148,6 +148,11 @@
|
|||||||
6419EC562AB8BC8B004A607A /* ContextInvitingContactMemberView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6419EC552AB8BC8B004A607A /* ContextInvitingContactMemberView.swift */; };
|
6419EC562AB8BC8B004A607A /* ContextInvitingContactMemberView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6419EC552AB8BC8B004A607A /* ContextInvitingContactMemberView.swift */; };
|
||||||
6419EC582AB97507004A607A /* CIMemberCreatedContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6419EC572AB97507004A607A /* CIMemberCreatedContactView.swift */; };
|
6419EC582AB97507004A607A /* CIMemberCreatedContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6419EC572AB97507004A607A /* CIMemberCreatedContactView.swift */; };
|
||||||
6432857C2925443C00FBE5C8 /* GroupPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6432857B2925443C00FBE5C8 /* GroupPreferencesView.swift */; };
|
6432857C2925443C00FBE5C8 /* GroupPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6432857B2925443C00FBE5C8 /* GroupPreferencesView.swift */; };
|
||||||
|
643B3B452CCBEB080083A2CF /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 643B3B402CCBEB080083A2CF /* libgmpxx.a */; };
|
||||||
|
643B3B462CCBEB080083A2CF /* libHSsimplex-chat-6.1.1.0-CTfGB7l09cqEHVIdvhrnH5-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 643B3B412CCBEB080083A2CF /* libHSsimplex-chat-6.1.1.0-CTfGB7l09cqEHVIdvhrnH5-ghc9.6.3.a */; };
|
||||||
|
643B3B472CCBEB080083A2CF /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 643B3B422CCBEB080083A2CF /* libffi.a */; };
|
||||||
|
643B3B482CCBEB080083A2CF /* libHSsimplex-chat-6.1.1.0-CTfGB7l09cqEHVIdvhrnH5.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 643B3B432CCBEB080083A2CF /* libHSsimplex-chat-6.1.1.0-CTfGB7l09cqEHVIdvhrnH5.a */; };
|
||||||
|
643B3B492CCBEB080083A2CF /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 643B3B442CCBEB080083A2CF /* libgmp.a */; };
|
||||||
6440CA00288857A10062C672 /* CIEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6440C9FF288857A10062C672 /* CIEventView.swift */; };
|
6440CA00288857A10062C672 /* CIEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6440C9FF288857A10062C672 /* CIEventView.swift */; };
|
||||||
6440CA03288AECA70062C672 /* AddGroupMembersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6440CA02288AECA70062C672 /* AddGroupMembersView.swift */; };
|
6440CA03288AECA70062C672 /* AddGroupMembersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6440CA02288AECA70062C672 /* AddGroupMembersView.swift */; };
|
||||||
6442E0BA287F169300CEC0F9 /* AddGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6442E0B9287F169300CEC0F9 /* AddGroupView.swift */; };
|
6442E0BA287F169300CEC0F9 /* AddGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6442E0B9287F169300CEC0F9 /* AddGroupView.swift */; };
|
||||||
@@ -204,6 +209,7 @@
|
|||||||
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */ = {isa = PBXBuildFile; productRef = CE38A29B2C3FCD72005ED185 /* SwiftyGif */; };
|
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */ = {isa = PBXBuildFile; productRef = CE38A29B2C3FCD72005ED185 /* SwiftyGif */; };
|
||||||
CE75480A2C622630009579B7 /* SwipeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7548092C622630009579B7 /* SwipeLabel.swift */; };
|
CE75480A2C622630009579B7 /* SwipeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7548092C622630009579B7 /* SwipeLabel.swift */; };
|
||||||
CE984D4B2C36C5D500E3AEFF /* ChatItemClipShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */; };
|
CE984D4B2C36C5D500E3AEFF /* ChatItemClipShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */; };
|
||||||
|
CEA6E91C2CBD21B0002B5DB4 /* UserDefault.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA6E91B2CBD21B0002B5DB4 /* UserDefault.swift */; };
|
||||||
CEDB245B2C9CD71800FBC5F6 /* StickyScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEDB245A2C9CD71800FBC5F6 /* StickyScrollView.swift */; };
|
CEDB245B2C9CD71800FBC5F6 /* StickyScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEDB245A2C9CD71800FBC5F6 /* StickyScrollView.swift */; };
|
||||||
CEDE70222C48FD9500233B1F /* SEChatState.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEDE70212C48FD9500233B1F /* SEChatState.swift */; };
|
CEDE70222C48FD9500233B1F /* SEChatState.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEDE70212C48FD9500233B1F /* SEChatState.swift */; };
|
||||||
CEE723AA2C3BD3D70009AE93 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE723A92C3BD3D70009AE93 /* ShareViewController.swift */; };
|
CEE723AA2C3BD3D70009AE93 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE723A92C3BD3D70009AE93 /* ShareViewController.swift */; };
|
||||||
@@ -211,17 +217,13 @@
|
|||||||
CEE723F02C3D25C70009AE93 /* ShareView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE723EF2C3D25C70009AE93 /* ShareView.swift */; };
|
CEE723F02C3D25C70009AE93 /* ShareView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE723EF2C3D25C70009AE93 /* ShareView.swift */; };
|
||||||
CEE723F22C3D25ED0009AE93 /* ShareModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE723F12C3D25ED0009AE93 /* ShareModel.swift */; };
|
CEE723F22C3D25ED0009AE93 /* ShareModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE723F12C3D25ED0009AE93 /* ShareModel.swift */; };
|
||||||
CEEA861D2C2ABCB50084E1EA /* ReverseList.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEEA861C2C2ABCB50084E1EA /* ReverseList.swift */; };
|
CEEA861D2C2ABCB50084E1EA /* ReverseList.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEEA861C2C2ABCB50084E1EA /* ReverseList.swift */; };
|
||||||
|
CEFB2EDF2CA1BCC7004B1ECE /* SheetRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEFB2EDE2CA1BCC7004B1ECE /* SheetRepresentable.swift */; };
|
||||||
D7197A1829AE89660055C05A /* WebRTC in Frameworks */ = {isa = PBXBuildFile; productRef = D7197A1729AE89660055C05A /* WebRTC */; };
|
D7197A1829AE89660055C05A /* WebRTC in Frameworks */ = {isa = PBXBuildFile; productRef = D7197A1729AE89660055C05A /* WebRTC */; };
|
||||||
D72A9088294BD7A70047C86D /* NativeTextEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A9087294BD7A70047C86D /* NativeTextEditor.swift */; };
|
D72A9088294BD7A70047C86D /* NativeTextEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A9087294BD7A70047C86D /* NativeTextEditor.swift */; };
|
||||||
D741547829AF89AF0022400A /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D741547729AF89AF0022400A /* StoreKit.framework */; };
|
D741547829AF89AF0022400A /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D741547729AF89AF0022400A /* StoreKit.framework */; };
|
||||||
D741547A29AF90B00022400A /* PushKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D741547929AF90B00022400A /* PushKit.framework */; };
|
D741547A29AF90B00022400A /* PushKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D741547929AF90B00022400A /* PushKit.framework */; };
|
||||||
D77B92DC2952372200A5A1CC /* SwiftyGif in Frameworks */ = {isa = PBXBuildFile; productRef = D77B92DB2952372200A5A1CC /* SwiftyGif */; };
|
D77B92DC2952372200A5A1CC /* SwiftyGif in Frameworks */ = {isa = PBXBuildFile; productRef = D77B92DB2952372200A5A1CC /* SwiftyGif */; };
|
||||||
D7F0E33929964E7E0068AF69 /* LZString in Frameworks */ = {isa = PBXBuildFile; productRef = D7F0E33829964E7E0068AF69 /* LZString */; };
|
D7F0E33929964E7E0068AF69 /* LZString in Frameworks */ = {isa = PBXBuildFile; productRef = D7F0E33829964E7E0068AF69 /* LZString */; };
|
||||||
E51B923B2CAB2B8800C212F2 /* libHSsimplex-chat-6.1.0.5-HWShuJBYoppEOt1hLB8GPU.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E51B92362CAB2B8800C212F2 /* libHSsimplex-chat-6.1.0.5-HWShuJBYoppEOt1hLB8GPU.a */; };
|
|
||||||
E51B923C2CAB2B8800C212F2 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E51B92372CAB2B8800C212F2 /* libgmp.a */; };
|
|
||||||
E51B923D2CAB2B8800C212F2 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E51B92382CAB2B8800C212F2 /* libffi.a */; };
|
|
||||||
E51B923E2CAB2B8800C212F2 /* libHSsimplex-chat-6.1.0.5-HWShuJBYoppEOt1hLB8GPU-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E51B92392CAB2B8800C212F2 /* libHSsimplex-chat-6.1.0.5-HWShuJBYoppEOt1hLB8GPU-ghc9.6.3.a */; };
|
|
||||||
E51B923F2CAB2B8800C212F2 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E51B923A2CAB2B8800C212F2 /* libgmpxx.a */; };
|
|
||||||
E51CC1E62C62085600DB91FE /* OneHandUICard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E51CC1E52C62085600DB91FE /* OneHandUICard.swift */; };
|
E51CC1E62C62085600DB91FE /* OneHandUICard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E51CC1E52C62085600DB91FE /* OneHandUICard.swift */; };
|
||||||
E5DCF8DB2C56FAC1007928CC /* SimpleXChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; };
|
E5DCF8DB2C56FAC1007928CC /* SimpleXChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; };
|
||||||
E5DCF9712C590272007928CC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E5DCF96F2C590272007928CC /* Localizable.strings */; };
|
E5DCF9712C590272007928CC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E5DCF96F2C590272007928CC /* Localizable.strings */; };
|
||||||
@@ -489,6 +491,11 @@
|
|||||||
6419EC552AB8BC8B004A607A /* ContextInvitingContactMemberView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextInvitingContactMemberView.swift; sourceTree = "<group>"; };
|
6419EC552AB8BC8B004A607A /* ContextInvitingContactMemberView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextInvitingContactMemberView.swift; sourceTree = "<group>"; };
|
||||||
6419EC572AB97507004A607A /* CIMemberCreatedContactView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIMemberCreatedContactView.swift; sourceTree = "<group>"; };
|
6419EC572AB97507004A607A /* CIMemberCreatedContactView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIMemberCreatedContactView.swift; sourceTree = "<group>"; };
|
||||||
6432857B2925443C00FBE5C8 /* GroupPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupPreferencesView.swift; sourceTree = "<group>"; };
|
6432857B2925443C00FBE5C8 /* GroupPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupPreferencesView.swift; sourceTree = "<group>"; };
|
||||||
|
643B3B402CCBEB080083A2CF /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgmpxx.a; path = Libraries/libgmpxx.a; sourceTree = "<group>"; };
|
||||||
|
643B3B412CCBEB080083A2CF /* libHSsimplex-chat-6.1.1.0-CTfGB7l09cqEHVIdvhrnH5-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libHSsimplex-chat-6.1.1.0-CTfGB7l09cqEHVIdvhrnH5-ghc9.6.3.a"; path = "Libraries/libHSsimplex-chat-6.1.1.0-CTfGB7l09cqEHVIdvhrnH5-ghc9.6.3.a"; sourceTree = "<group>"; };
|
||||||
|
643B3B422CCBEB080083A2CF /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libffi.a; path = Libraries/libffi.a; sourceTree = "<group>"; };
|
||||||
|
643B3B432CCBEB080083A2CF /* libHSsimplex-chat-6.1.1.0-CTfGB7l09cqEHVIdvhrnH5.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libHSsimplex-chat-6.1.1.0-CTfGB7l09cqEHVIdvhrnH5.a"; path = "Libraries/libHSsimplex-chat-6.1.1.0-CTfGB7l09cqEHVIdvhrnH5.a"; sourceTree = "<group>"; };
|
||||||
|
643B3B442CCBEB080083A2CF /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgmp.a; path = Libraries/libgmp.a; sourceTree = "<group>"; };
|
||||||
6440C9FF288857A10062C672 /* CIEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIEventView.swift; sourceTree = "<group>"; };
|
6440C9FF288857A10062C672 /* CIEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIEventView.swift; sourceTree = "<group>"; };
|
||||||
6440CA02288AECA70062C672 /* AddGroupMembersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddGroupMembersView.swift; sourceTree = "<group>"; };
|
6440CA02288AECA70062C672 /* AddGroupMembersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddGroupMembersView.swift; sourceTree = "<group>"; };
|
||||||
6442E0B9287F169300CEC0F9 /* AddGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddGroupView.swift; sourceTree = "<group>"; };
|
6442E0B9287F169300CEC0F9 /* AddGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddGroupView.swift; sourceTree = "<group>"; };
|
||||||
@@ -544,6 +551,7 @@
|
|||||||
CE3097FA2C4C0C9F00180898 /* ErrorAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorAlert.swift; sourceTree = "<group>"; };
|
CE3097FA2C4C0C9F00180898 /* ErrorAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorAlert.swift; sourceTree = "<group>"; };
|
||||||
CE7548092C622630009579B7 /* SwipeLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeLabel.swift; sourceTree = "<group>"; };
|
CE7548092C622630009579B7 /* SwipeLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeLabel.swift; sourceTree = "<group>"; };
|
||||||
CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemClipShape.swift; sourceTree = "<group>"; };
|
CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemClipShape.swift; sourceTree = "<group>"; };
|
||||||
|
CEA6E91B2CBD21B0002B5DB4 /* UserDefault.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefault.swift; sourceTree = "<group>"; };
|
||||||
CEDB245A2C9CD71800FBC5F6 /* StickyScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickyScrollView.swift; sourceTree = "<group>"; };
|
CEDB245A2C9CD71800FBC5F6 /* StickyScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickyScrollView.swift; sourceTree = "<group>"; };
|
||||||
CEDE70212C48FD9500233B1F /* SEChatState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SEChatState.swift; sourceTree = "<group>"; };
|
CEDE70212C48FD9500233B1F /* SEChatState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SEChatState.swift; sourceTree = "<group>"; };
|
||||||
CEE723A72C3BD3D70009AE93 /* SimpleX SE.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "SimpleX SE.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
CEE723A72C3BD3D70009AE93 /* SimpleX SE.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "SimpleX SE.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
@@ -553,15 +561,11 @@
|
|||||||
CEE723EF2C3D25C70009AE93 /* ShareView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareView.swift; sourceTree = "<group>"; };
|
CEE723EF2C3D25C70009AE93 /* ShareView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareView.swift; sourceTree = "<group>"; };
|
||||||
CEE723F12C3D25ED0009AE93 /* ShareModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareModel.swift; sourceTree = "<group>"; };
|
CEE723F12C3D25ED0009AE93 /* ShareModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareModel.swift; sourceTree = "<group>"; };
|
||||||
CEEA861C2C2ABCB50084E1EA /* ReverseList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReverseList.swift; sourceTree = "<group>"; };
|
CEEA861C2C2ABCB50084E1EA /* ReverseList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReverseList.swift; sourceTree = "<group>"; };
|
||||||
|
CEFB2EDE2CA1BCC7004B1ECE /* SheetRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetRepresentable.swift; sourceTree = "<group>"; };
|
||||||
D72A9087294BD7A70047C86D /* NativeTextEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeTextEditor.swift; sourceTree = "<group>"; };
|
D72A9087294BD7A70047C86D /* NativeTextEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeTextEditor.swift; sourceTree = "<group>"; };
|
||||||
D741547729AF89AF0022400A /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.1.sdk/System/Library/Frameworks/StoreKit.framework; sourceTree = DEVELOPER_DIR; };
|
D741547729AF89AF0022400A /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.1.sdk/System/Library/Frameworks/StoreKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
D741547929AF90B00022400A /* PushKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PushKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.1.sdk/System/Library/Frameworks/PushKit.framework; sourceTree = DEVELOPER_DIR; };
|
D741547929AF90B00022400A /* PushKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PushKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.1.sdk/System/Library/Frameworks/PushKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
D7AA2C3429A936B400737B40 /* MediaEncryption.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; name = MediaEncryption.playground; path = Shared/MediaEncryption.playground; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
D7AA2C3429A936B400737B40 /* MediaEncryption.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; name = MediaEncryption.playground; path = Shared/MediaEncryption.playground; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||||
E51B92362CAB2B8800C212F2 /* libHSsimplex-chat-6.1.0.5-HWShuJBYoppEOt1hLB8GPU.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.1.0.5-HWShuJBYoppEOt1hLB8GPU.a"; sourceTree = "<group>"; };
|
|
||||||
E51B92372CAB2B8800C212F2 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
|
|
||||||
E51B92382CAB2B8800C212F2 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
|
|
||||||
E51B92392CAB2B8800C212F2 /* libHSsimplex-chat-6.1.0.5-HWShuJBYoppEOt1hLB8GPU-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.1.0.5-HWShuJBYoppEOt1hLB8GPU-ghc9.6.3.a"; sourceTree = "<group>"; };
|
|
||||||
E51B923A2CAB2B8800C212F2 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
|
|
||||||
E51CC1E52C62085600DB91FE /* OneHandUICard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OneHandUICard.swift; sourceTree = "<group>"; };
|
E51CC1E52C62085600DB91FE /* OneHandUICard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OneHandUICard.swift; sourceTree = "<group>"; };
|
||||||
E5DCF9702C590272007928CC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
E5DCF9702C590272007928CC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
E5DCF9722C590274007928CC /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/Localizable.strings; sourceTree = "<group>"; };
|
E5DCF9722C590274007928CC /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
@@ -653,14 +657,14 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
E51B923B2CAB2B8800C212F2 /* libHSsimplex-chat-6.1.0.5-HWShuJBYoppEOt1hLB8GPU.a in Frameworks */,
|
643B3B452CCBEB080083A2CF /* libgmpxx.a in Frameworks */,
|
||||||
E51B923D2CAB2B8800C212F2 /* libffi.a in Frameworks */,
|
643B3B472CCBEB080083A2CF /* libffi.a in Frameworks */,
|
||||||
E51B923C2CAB2B8800C212F2 /* libgmp.a in Frameworks */,
|
643B3B492CCBEB080083A2CF /* libgmp.a in Frameworks */,
|
||||||
5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */,
|
5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */,
|
||||||
E51B923F2CAB2B8800C212F2 /* libgmpxx.a in Frameworks */,
|
|
||||||
5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */,
|
5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */,
|
||||||
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */,
|
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */,
|
||||||
E51B923E2CAB2B8800C212F2 /* libHSsimplex-chat-6.1.0.5-HWShuJBYoppEOt1hLB8GPU-ghc9.6.3.a in Frameworks */,
|
643B3B482CCBEB080083A2CF /* libHSsimplex-chat-6.1.1.0-CTfGB7l09cqEHVIdvhrnH5.a in Frameworks */,
|
||||||
|
643B3B462CCBEB080083A2CF /* libHSsimplex-chat-6.1.1.0-CTfGB7l09cqEHVIdvhrnH5-ghc9.6.3.a in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -737,11 +741,6 @@
|
|||||||
5C764E5C279C70B7000C6508 /* Libraries */ = {
|
5C764E5C279C70B7000C6508 /* Libraries */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E51B92382CAB2B8800C212F2 /* libffi.a */,
|
|
||||||
E51B92372CAB2B8800C212F2 /* libgmp.a */,
|
|
||||||
E51B923A2CAB2B8800C212F2 /* libgmpxx.a */,
|
|
||||||
E51B92392CAB2B8800C212F2 /* libHSsimplex-chat-6.1.0.5-HWShuJBYoppEOt1hLB8GPU-ghc9.6.3.a */,
|
|
||||||
E51B92362CAB2B8800C212F2 /* libHSsimplex-chat-6.1.0.5-HWShuJBYoppEOt1hLB8GPU.a */,
|
|
||||||
);
|
);
|
||||||
path = Libraries;
|
path = Libraries;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -799,6 +798,8 @@
|
|||||||
CE7548092C622630009579B7 /* SwipeLabel.swift */,
|
CE7548092C622630009579B7 /* SwipeLabel.swift */,
|
||||||
CE176F1F2C87014C00145DBC /* InvertedForegroundStyle.swift */,
|
CE176F1F2C87014C00145DBC /* InvertedForegroundStyle.swift */,
|
||||||
CEDB245A2C9CD71800FBC5F6 /* StickyScrollView.swift */,
|
CEDB245A2C9CD71800FBC5F6 /* StickyScrollView.swift */,
|
||||||
|
CEFB2EDE2CA1BCC7004B1ECE /* SheetRepresentable.swift */,
|
||||||
|
CEA6E91B2CBD21B0002B5DB4 /* UserDefault.swift */,
|
||||||
);
|
);
|
||||||
path = Helpers;
|
path = Helpers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -811,6 +812,11 @@
|
|||||||
5CC2C0FA2809BF11000C35E3 /* Localizable.strings */,
|
5CC2C0FA2809BF11000C35E3 /* Localizable.strings */,
|
||||||
5C422A7C27A9A6FA0097A1E1 /* SimpleX (iOS).entitlements */,
|
5C422A7C27A9A6FA0097A1E1 /* SimpleX (iOS).entitlements */,
|
||||||
5C764E5C279C70B7000C6508 /* Libraries */,
|
5C764E5C279C70B7000C6508 /* Libraries */,
|
||||||
|
643B3B422CCBEB080083A2CF /* libffi.a */,
|
||||||
|
643B3B442CCBEB080083A2CF /* libgmp.a */,
|
||||||
|
643B3B402CCBEB080083A2CF /* libgmpxx.a */,
|
||||||
|
643B3B412CCBEB080083A2CF /* libHSsimplex-chat-6.1.1.0-CTfGB7l09cqEHVIdvhrnH5-ghc9.6.3.a */,
|
||||||
|
643B3B432CCBEB080083A2CF /* libHSsimplex-chat-6.1.1.0-CTfGB7l09cqEHVIdvhrnH5.a */,
|
||||||
5CA059C2279559F40002BEB4 /* Shared */,
|
5CA059C2279559F40002BEB4 /* Shared */,
|
||||||
5CDCAD462818589900503DA2 /* SimpleX NSE */,
|
5CDCAD462818589900503DA2 /* SimpleX NSE */,
|
||||||
CEE723A82C3BD3D70009AE93 /* SimpleX SE */,
|
CEE723A82C3BD3D70009AE93 /* SimpleX SE */,
|
||||||
@@ -906,10 +912,9 @@
|
|||||||
5CB924DF27A8678B00ACCCDD /* UserSettings */ = {
|
5CB924DF27A8678B00ACCCDD /* UserSettings */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
643B3B4C2CCFD34B0083A2CF /* NetworkAndServers */,
|
||||||
5CB924D627A8563F00ACCCDD /* SettingsView.swift */,
|
5CB924D627A8563F00ACCCDD /* SettingsView.swift */,
|
||||||
5CB346E62868D76D001FD2EF /* NotificationsView.swift */,
|
5CB346E62868D76D001FD2EF /* NotificationsView.swift */,
|
||||||
5C9C2DA6289957AE00CC63B1 /* AdvancedNetworkSettings.swift */,
|
|
||||||
5C9C2DA82899DA6F00CC63B1 /* NetworkAndServers.swift */,
|
|
||||||
5CADE79929211BB900072E13 /* PreferencesView.swift */,
|
5CADE79929211BB900072E13 /* PreferencesView.swift */,
|
||||||
5C5DB70D289ABDD200730FFF /* AppearanceSettings.swift */,
|
5C5DB70D289ABDD200730FFF /* AppearanceSettings.swift */,
|
||||||
5C05DF522840AA1D00C683F9 /* CallSettings.swift */,
|
5C05DF522840AA1D00C683F9 /* CallSettings.swift */,
|
||||||
@@ -917,9 +922,6 @@
|
|||||||
5CC036DF29C488D500C0EF20 /* HiddenProfileView.swift */,
|
5CC036DF29C488D500C0EF20 /* HiddenProfileView.swift */,
|
||||||
5C577F7C27C83AA10006112D /* MarkdownHelp.swift */,
|
5C577F7C27C83AA10006112D /* MarkdownHelp.swift */,
|
||||||
5C3F1D57284363C400EC8A82 /* PrivacySettings.swift */,
|
5C3F1D57284363C400EC8A82 /* PrivacySettings.swift */,
|
||||||
5C93292E29239A170090FFF9 /* ProtocolServersView.swift */,
|
|
||||||
5C93293029239BED0090FFF9 /* ProtocolServerView.swift */,
|
|
||||||
5C9329402929248A0090FFF9 /* ScanProtocolServer.swift */,
|
|
||||||
5CB2084E28DA4B4800D024EC /* RTCServers.swift */,
|
5CB2084E28DA4B4800D024EC /* RTCServers.swift */,
|
||||||
64F1CC3A28B39D8600CD1FB1 /* IncognitoHelp.swift */,
|
64F1CC3A28B39D8600CD1FB1 /* IncognitoHelp.swift */,
|
||||||
18415845648CA4F5A8BCA272 /* UserProfilesView.swift */,
|
18415845648CA4F5A8BCA272 /* UserProfilesView.swift */,
|
||||||
@@ -1050,6 +1052,18 @@
|
|||||||
path = Database;
|
path = Database;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
643B3B4C2CCFD34B0083A2CF /* NetworkAndServers */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
5C9329402929248A0090FFF9 /* ScanProtocolServer.swift */,
|
||||||
|
5C93293029239BED0090FFF9 /* ProtocolServerView.swift */,
|
||||||
|
5C93292E29239A170090FFF9 /* ProtocolServersView.swift */,
|
||||||
|
5C9C2DA6289957AE00CC63B1 /* AdvancedNetworkSettings.swift */,
|
||||||
|
5C9C2DA82899DA6F00CC63B1 /* NetworkAndServers.swift */,
|
||||||
|
);
|
||||||
|
path = NetworkAndServers;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
6440CA01288AEC770062C672 /* Group */ = {
|
6440CA01288AEC770062C672 /* Group */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -1449,6 +1463,7 @@
|
|||||||
5CB634B129E5EFEA0066AD6B /* PasscodeView.swift in Sources */,
|
5CB634B129E5EFEA0066AD6B /* PasscodeView.swift in Sources */,
|
||||||
8C69FE7D2B8C7D2700267E38 /* AppSettings.swift in Sources */,
|
8C69FE7D2B8C7D2700267E38 /* AppSettings.swift in Sources */,
|
||||||
5C2E260F27A30FDC00F70299 /* ChatView.swift in Sources */,
|
5C2E260F27A30FDC00F70299 /* ChatView.swift in Sources */,
|
||||||
|
CEFB2EDF2CA1BCC7004B1ECE /* SheetRepresentable.swift in Sources */,
|
||||||
5C2E260B27A30CFA00F70299 /* ChatListView.swift in Sources */,
|
5C2E260B27A30CFA00F70299 /* ChatListView.swift in Sources */,
|
||||||
6442E0BA287F169300CEC0F9 /* AddGroupView.swift in Sources */,
|
6442E0BA287F169300CEC0F9 /* AddGroupView.swift in Sources */,
|
||||||
5CF937232B2503D000E1D781 /* NSESubscriber.swift in Sources */,
|
5CF937232B2503D000E1D781 /* NSESubscriber.swift in Sources */,
|
||||||
@@ -1478,6 +1493,7 @@
|
|||||||
5CFA59D12864782E00863A68 /* ChatArchiveView.swift in Sources */,
|
5CFA59D12864782E00863A68 /* ChatArchiveView.swift in Sources */,
|
||||||
649BCDA22805D6EF00C3A862 /* CIImageView.swift in Sources */,
|
649BCDA22805D6EF00C3A862 /* CIImageView.swift in Sources */,
|
||||||
5CADE79C292131E900072E13 /* ContactPreferencesView.swift in Sources */,
|
5CADE79C292131E900072E13 /* ContactPreferencesView.swift in Sources */,
|
||||||
|
CEA6E91C2CBD21B0002B5DB4 /* UserDefault.swift in Sources */,
|
||||||
5CB346E52868AA7F001FD2EF /* SuspendChat.swift in Sources */,
|
5CB346E52868AA7F001FD2EF /* SuspendChat.swift in Sources */,
|
||||||
5C9C2DA52894777E00CC63B1 /* GroupProfileView.swift in Sources */,
|
5C9C2DA52894777E00CC63B1 /* GroupProfileView.swift in Sources */,
|
||||||
5CEACCED27DEA495000BD591 /* MsgContentView.swift in Sources */,
|
5CEACCED27DEA495000BD591 /* MsgContentView.swift in Sources */,
|
||||||
@@ -1895,7 +1911,7 @@
|
|||||||
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
|
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 241;
|
CURRENT_PROJECT_VERSION = 245;
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
@@ -1920,7 +1936,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
LLVM_LTO = YES_THIN;
|
LLVM_LTO = YES_THIN;
|
||||||
MARKETING_VERSION = 6.1;
|
MARKETING_VERSION = 6.1.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
|
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
|
||||||
PRODUCT_NAME = SimpleX;
|
PRODUCT_NAME = SimpleX;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -1944,7 +1960,7 @@
|
|||||||
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
|
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 241;
|
CURRENT_PROJECT_VERSION = 245;
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
@@ -1969,7 +1985,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
LLVM_LTO = YES;
|
LLVM_LTO = YES;
|
||||||
MARKETING_VERSION = 6.1;
|
MARKETING_VERSION = 6.1.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
|
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
|
||||||
PRODUCT_NAME = SimpleX;
|
PRODUCT_NAME = SimpleX;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -1985,11 +2001,11 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 241;
|
CURRENT_PROJECT_VERSION = 245;
|
||||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MARKETING_VERSION = 6.1;
|
MARKETING_VERSION = 6.1.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
|
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -2005,11 +2021,11 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 241;
|
CURRENT_PROJECT_VERSION = 245;
|
||||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MARKETING_VERSION = 6.1;
|
MARKETING_VERSION = 6.1.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
|
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -2030,7 +2046,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 241;
|
CURRENT_PROJECT_VERSION = 245;
|
||||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
GCC_OPTIMIZATION_LEVEL = s;
|
GCC_OPTIMIZATION_LEVEL = s;
|
||||||
@@ -2045,7 +2061,7 @@
|
|||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
LLVM_LTO = YES;
|
LLVM_LTO = YES;
|
||||||
MARKETING_VERSION = 6.1;
|
MARKETING_VERSION = 6.1.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
|
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
@@ -2067,7 +2083,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 241;
|
CURRENT_PROJECT_VERSION = 245;
|
||||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
ENABLE_CODE_COVERAGE = NO;
|
ENABLE_CODE_COVERAGE = NO;
|
||||||
@@ -2082,7 +2098,7 @@
|
|||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
LLVM_LTO = YES;
|
LLVM_LTO = YES;
|
||||||
MARKETING_VERSION = 6.1;
|
MARKETING_VERSION = 6.1.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
|
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
@@ -2104,7 +2120,7 @@
|
|||||||
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
|
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
|
||||||
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 241;
|
CURRENT_PROJECT_VERSION = 245;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
@@ -2130,7 +2146,7 @@
|
|||||||
"$(PROJECT_DIR)/Libraries/sim",
|
"$(PROJECT_DIR)/Libraries/sim",
|
||||||
);
|
);
|
||||||
LLVM_LTO = YES;
|
LLVM_LTO = YES;
|
||||||
MARKETING_VERSION = 6.1;
|
MARKETING_VERSION = 6.1.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
|
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -2155,7 +2171,7 @@
|
|||||||
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
|
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
|
||||||
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 241;
|
CURRENT_PROJECT_VERSION = 245;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
@@ -2181,7 +2197,7 @@
|
|||||||
"$(PROJECT_DIR)/Libraries/sim",
|
"$(PROJECT_DIR)/Libraries/sim",
|
||||||
);
|
);
|
||||||
LLVM_LTO = YES;
|
LLVM_LTO = YES;
|
||||||
MARKETING_VERSION = 6.1;
|
MARKETING_VERSION = 6.1.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
|
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -2206,7 +2222,7 @@
|
|||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 241;
|
CURRENT_PROJECT_VERSION = 245;
|
||||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
@@ -2221,7 +2237,7 @@
|
|||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
MARKETING_VERSION = 6.1;
|
MARKETING_VERSION = 6.1.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
|
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -2240,7 +2256,7 @@
|
|||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 241;
|
CURRENT_PROJECT_VERSION = 245;
|
||||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
@@ -2255,7 +2271,7 @@
|
|||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
MARKETING_VERSION = 6.1;
|
MARKETING_VERSION = 6.1.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
|
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ public enum ChatCommand {
|
|||||||
case apiRegisterToken(token: DeviceToken, notificationMode: NotificationsMode)
|
case apiRegisterToken(token: DeviceToken, notificationMode: NotificationsMode)
|
||||||
case apiVerifyToken(token: DeviceToken, nonce: String, code: String)
|
case apiVerifyToken(token: DeviceToken, nonce: String, code: String)
|
||||||
case apiDeleteToken(token: DeviceToken)
|
case apiDeleteToken(token: DeviceToken)
|
||||||
case apiGetNtfMessage(nonce: String, encNtfInfo: String)
|
case apiGetNtfConns(nonce: String, encNtfInfo: String)
|
||||||
|
case apiGetConnNtfMessages(connIds: [String])
|
||||||
case apiNewGroup(userId: Int64, incognito: Bool, groupProfile: GroupProfile)
|
case apiNewGroup(userId: Int64, incognito: Bool, groupProfile: GroupProfile)
|
||||||
case apiAddMember(groupId: Int64, contactId: Int64, memberRole: GroupMemberRole)
|
case apiAddMember(groupId: Int64, contactId: Int64, memberRole: GroupMemberRole)
|
||||||
case apiJoinGroup(groupId: Int64)
|
case apiJoinGroup(groupId: Int64)
|
||||||
@@ -213,7 +214,8 @@ public enum ChatCommand {
|
|||||||
case let .apiRegisterToken(token, notificationMode): return "/_ntf register \(token.cmdString) \(notificationMode.rawValue)"
|
case let .apiRegisterToken(token, notificationMode): return "/_ntf register \(token.cmdString) \(notificationMode.rawValue)"
|
||||||
case let .apiVerifyToken(token, nonce, code): return "/_ntf verify \(token.cmdString) \(nonce) \(code)"
|
case let .apiVerifyToken(token, nonce, code): return "/_ntf verify \(token.cmdString) \(nonce) \(code)"
|
||||||
case let .apiDeleteToken(token): return "/_ntf delete \(token.cmdString)"
|
case let .apiDeleteToken(token): return "/_ntf delete \(token.cmdString)"
|
||||||
case let .apiGetNtfMessage(nonce, encNtfInfo): return "/_ntf message \(nonce) \(encNtfInfo)"
|
case let .apiGetNtfConns(nonce, encNtfInfo): return "/_ntf conns \(nonce) \(encNtfInfo)"
|
||||||
|
case let .apiGetConnNtfMessages(connIds): return "/_ntf conn messages \(connIds.joined(separator: ","))"
|
||||||
case let .apiNewGroup(userId, incognito, groupProfile): return "/_group \(userId) incognito=\(onOff(incognito)) \(encodeJSON(groupProfile))"
|
case let .apiNewGroup(userId, incognito, groupProfile): return "/_group \(userId) incognito=\(onOff(incognito)) \(encodeJSON(groupProfile))"
|
||||||
case let .apiAddMember(groupId, contactId, memberRole): return "/_add #\(groupId) \(contactId) \(memberRole)"
|
case let .apiAddMember(groupId, contactId, memberRole): return "/_add #\(groupId) \(contactId) \(memberRole)"
|
||||||
case let .apiJoinGroup(groupId): return "/_join #\(groupId)"
|
case let .apiJoinGroup(groupId): return "/_join #\(groupId)"
|
||||||
@@ -367,7 +369,8 @@ public enum ChatCommand {
|
|||||||
case .apiRegisterToken: return "apiRegisterToken"
|
case .apiRegisterToken: return "apiRegisterToken"
|
||||||
case .apiVerifyToken: return "apiVerifyToken"
|
case .apiVerifyToken: return "apiVerifyToken"
|
||||||
case .apiDeleteToken: return "apiDeleteToken"
|
case .apiDeleteToken: return "apiDeleteToken"
|
||||||
case .apiGetNtfMessage: return "apiGetNtfMessage"
|
case .apiGetNtfConns: return "apiGetNtfConns"
|
||||||
|
case .apiGetConnNtfMessages: return "apiGetConnNtfMessages"
|
||||||
case .apiNewGroup: return "apiNewGroup"
|
case .apiNewGroup: return "apiNewGroup"
|
||||||
case .apiAddMember: return "apiAddMember"
|
case .apiAddMember: return "apiAddMember"
|
||||||
case .apiJoinGroup: return "apiJoinGroup"
|
case .apiJoinGroup: return "apiJoinGroup"
|
||||||
@@ -679,8 +682,9 @@ public enum ChatResponse: Decodable, Error {
|
|||||||
case callInvitations(callInvitations: [RcvCallInvitation])
|
case callInvitations(callInvitations: [RcvCallInvitation])
|
||||||
case ntfTokenStatus(status: NtfTknStatus)
|
case ntfTokenStatus(status: NtfTknStatus)
|
||||||
case ntfToken(token: DeviceToken, status: NtfTknStatus, ntfMode: NotificationsMode, ntfServer: String)
|
case ntfToken(token: DeviceToken, status: NtfTknStatus, ntfMode: NotificationsMode, ntfServer: String)
|
||||||
case ntfMessages(user_: User?, connEntity_: ConnectionEntity?, msgTs: Date?, ntfMessage_: NtfMsgInfo?)
|
case ntfConns(ntfConns: [NtfConn])
|
||||||
case ntfMessage(user: UserRef, connEntity: ConnectionEntity, ntfMessage: NtfMsgInfo)
|
case connNtfMessages(receivedMsgs: [NtfMsgInfo?])
|
||||||
|
case ntfMessage(user: UserRef, connEntity: ConnectionEntity, ntfMessage: NtfMsgAckInfo)
|
||||||
case contactConnectionDeleted(user: UserRef, connection: PendingContactConnection)
|
case contactConnectionDeleted(user: UserRef, connection: PendingContactConnection)
|
||||||
case contactDisabled(user: UserRef, contact: Contact)
|
case contactDisabled(user: UserRef, contact: Contact)
|
||||||
// remote desktop responses/events
|
// remote desktop responses/events
|
||||||
@@ -847,7 +851,8 @@ public enum ChatResponse: Decodable, Error {
|
|||||||
case .callInvitations: return "callInvitations"
|
case .callInvitations: return "callInvitations"
|
||||||
case .ntfTokenStatus: return "ntfTokenStatus"
|
case .ntfTokenStatus: return "ntfTokenStatus"
|
||||||
case .ntfToken: return "ntfToken"
|
case .ntfToken: return "ntfToken"
|
||||||
case .ntfMessages: return "ntfMessages"
|
case .ntfConns: return "ntfConns"
|
||||||
|
case .connNtfMessages: return "connNtfMessages"
|
||||||
case .ntfMessage: return "ntfMessage"
|
case .ntfMessage: return "ntfMessage"
|
||||||
case .contactConnectionDeleted: return "contactConnectionDeleted"
|
case .contactConnectionDeleted: return "contactConnectionDeleted"
|
||||||
case .contactDisabled: return "contactDisabled"
|
case .contactDisabled: return "contactDisabled"
|
||||||
@@ -1024,7 +1029,8 @@ public enum ChatResponse: Decodable, Error {
|
|||||||
case let .callInvitations(invs): return String(describing: invs)
|
case let .callInvitations(invs): return String(describing: invs)
|
||||||
case let .ntfTokenStatus(status): return String(describing: status)
|
case let .ntfTokenStatus(status): return String(describing: status)
|
||||||
case let .ntfToken(token, status, ntfMode, ntfServer): return "token: \(token)\nstatus: \(status.rawValue)\nntfMode: \(ntfMode.rawValue)\nntfServer: \(ntfServer)"
|
case let .ntfToken(token, status, ntfMode, ntfServer): return "token: \(token)\nstatus: \(status.rawValue)\nntfMode: \(ntfMode.rawValue)\nntfServer: \(ntfServer)"
|
||||||
case let .ntfMessages(u, connEntity, msgTs, ntfMessages): return withUser(u, "connEntity: \(String(describing: connEntity))\nmsgTs: \(String(describing: msgTs))\nntfMessages: \(String(describing: ntfMessages))")
|
case let .ntfConns(ntfConns): return String(describing: ntfConns)
|
||||||
|
case let .connNtfMessages(receivedMsgs): return "receivedMsgs: \(String(describing: receivedMsgs))"
|
||||||
case let .ntfMessage(u, connEntity, ntfMessage): return withUser(u, "connEntity: \(String(describing: connEntity))\nntfMessage: \(String(describing: ntfMessage))")
|
case let .ntfMessage(u, connEntity, ntfMessage): return withUser(u, "connEntity: \(String(describing: connEntity))\nntfMessage: \(String(describing: ntfMessage))")
|
||||||
case let .contactConnectionDeleted(u, connection): return withUser(u, String(describing: connection))
|
case let .contactConnectionDeleted(u, connection): return withUser(u, String(describing: connection))
|
||||||
case let .contactDisabled(u, contact): return withUser(u, String(describing: contact))
|
case let .contactDisabled(u, contact): return withUser(u, String(describing: contact))
|
||||||
@@ -1353,7 +1359,7 @@ public struct NetCfg: Codable, Equatable {
|
|||||||
public var sessionMode = TransportSessionMode.user
|
public var sessionMode = TransportSessionMode.user
|
||||||
public var smpProxyMode: SMPProxyMode = .unknown
|
public var smpProxyMode: SMPProxyMode = .unknown
|
||||||
public var smpProxyFallback: SMPProxyFallback = .allowProtected
|
public var smpProxyFallback: SMPProxyFallback = .allowProtected
|
||||||
var smpWebPort = false
|
public var smpWebPort = false
|
||||||
public var tcpConnectTimeout: Int // microseconds
|
public var tcpConnectTimeout: Int // microseconds
|
||||||
public var tcpTimeout: Int // microseconds
|
public var tcpTimeout: Int // microseconds
|
||||||
public var tcpTimeoutPerKb: Int // microseconds
|
public var tcpTimeoutPerKb: Int // microseconds
|
||||||
@@ -1485,18 +1491,22 @@ public enum OnionHosts: String, Identifiable {
|
|||||||
|
|
||||||
public enum TransportSessionMode: String, Codable, Identifiable {
|
public enum TransportSessionMode: String, Codable, Identifiable {
|
||||||
case user
|
case user
|
||||||
|
case session
|
||||||
|
case server
|
||||||
case entity
|
case entity
|
||||||
|
|
||||||
public var text: LocalizedStringKey {
|
public var text: LocalizedStringKey {
|
||||||
switch self {
|
switch self {
|
||||||
case .user: return "User profile"
|
case .user: return "Chat profile"
|
||||||
|
case .session: return "App session"
|
||||||
|
case .server: return "Server"
|
||||||
case .entity: return "Connection"
|
case .entity: return "Connection"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public var id: TransportSessionMode { self }
|
public var id: TransportSessionMode { self }
|
||||||
|
|
||||||
public static let values: [TransportSessionMode] = [.user, .entity]
|
public static let values: [TransportSessionMode] = [.user, .session, .server, .entity]
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct KeepAliveOpts: Codable, Equatable {
|
public struct KeepAliveOpts: Codable, Equatable {
|
||||||
@@ -2031,7 +2041,7 @@ public enum SQLiteError: Decodable, Hashable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum AgentErrorType: Decodable, Hashable {
|
public enum AgentErrorType: Decodable, Hashable {
|
||||||
case CMD(cmdErr: CommandErrorType)
|
case CMD(cmdErr: CommandErrorType, errContext: String)
|
||||||
case CONN(connErr: ConnectionErrorType)
|
case CONN(connErr: ConnectionErrorType)
|
||||||
case SMP(serverAddress: String, smpErr: ProtocolErrorType)
|
case SMP(serverAddress: String, smpErr: ProtocolErrorType)
|
||||||
case NTF(ntfErr: ProtocolErrorType)
|
case NTF(ntfErr: ProtocolErrorType)
|
||||||
@@ -2078,6 +2088,7 @@ public enum ProtocolErrorType: Decodable, Hashable {
|
|||||||
case AUTH
|
case AUTH
|
||||||
case CRYPTO
|
case CRYPTO
|
||||||
case QUOTA
|
case QUOTA
|
||||||
|
case STORE(storeErr: String)
|
||||||
case NO_MSG
|
case NO_MSG
|
||||||
case LARGE_MSG
|
case LARGE_MSG
|
||||||
case EXPIRED
|
case EXPIRED
|
||||||
@@ -2251,6 +2262,8 @@ public struct AppSettings: Codable, Equatable {
|
|||||||
public var iosCallKitEnabled: Bool? = nil
|
public var iosCallKitEnabled: Bool? = nil
|
||||||
public var iosCallKitCallsInRecents: Bool? = nil
|
public var iosCallKitCallsInRecents: Bool? = nil
|
||||||
public var uiProfileImageCornerRadius: Double? = nil
|
public var uiProfileImageCornerRadius: Double? = nil
|
||||||
|
public var uiChatItemRoundness: Double? = nil
|
||||||
|
public var uiChatItemTail: Bool? = nil
|
||||||
public var uiColorScheme: String? = nil
|
public var uiColorScheme: String? = nil
|
||||||
public var uiDarkColorScheme: String? = nil
|
public var uiDarkColorScheme: String? = nil
|
||||||
public var uiCurrentThemeIds: [String: String]? = nil
|
public var uiCurrentThemeIds: [String: String]? = nil
|
||||||
@@ -2283,6 +2296,8 @@ public struct AppSettings: Codable, Equatable {
|
|||||||
if iosCallKitEnabled != def.iosCallKitEnabled { empty.iosCallKitEnabled = iosCallKitEnabled }
|
if iosCallKitEnabled != def.iosCallKitEnabled { empty.iosCallKitEnabled = iosCallKitEnabled }
|
||||||
if iosCallKitCallsInRecents != def.iosCallKitCallsInRecents { empty.iosCallKitCallsInRecents = iosCallKitCallsInRecents }
|
if iosCallKitCallsInRecents != def.iosCallKitCallsInRecents { empty.iosCallKitCallsInRecents = iosCallKitCallsInRecents }
|
||||||
if uiProfileImageCornerRadius != def.uiProfileImageCornerRadius { empty.uiProfileImageCornerRadius = uiProfileImageCornerRadius }
|
if uiProfileImageCornerRadius != def.uiProfileImageCornerRadius { empty.uiProfileImageCornerRadius = uiProfileImageCornerRadius }
|
||||||
|
if uiChatItemRoundness != def.uiChatItemRoundness { empty.uiChatItemRoundness = uiChatItemRoundness }
|
||||||
|
if uiChatItemTail != def.uiChatItemTail { empty.uiChatItemTail = uiChatItemTail }
|
||||||
if uiColorScheme != def.uiColorScheme { empty.uiColorScheme = uiColorScheme }
|
if uiColorScheme != def.uiColorScheme { empty.uiColorScheme = uiColorScheme }
|
||||||
if uiDarkColorScheme != def.uiDarkColorScheme { empty.uiDarkColorScheme = uiDarkColorScheme }
|
if uiDarkColorScheme != def.uiDarkColorScheme { empty.uiDarkColorScheme = uiDarkColorScheme }
|
||||||
if uiCurrentThemeIds != def.uiCurrentThemeIds { empty.uiCurrentThemeIds = uiCurrentThemeIds }
|
if uiCurrentThemeIds != def.uiCurrentThemeIds { empty.uiCurrentThemeIds = uiCurrentThemeIds }
|
||||||
@@ -2316,6 +2331,8 @@ public struct AppSettings: Codable, Equatable {
|
|||||||
iosCallKitEnabled: true,
|
iosCallKitEnabled: true,
|
||||||
iosCallKitCallsInRecents: false,
|
iosCallKitCallsInRecents: false,
|
||||||
uiProfileImageCornerRadius: 22.5,
|
uiProfileImageCornerRadius: 22.5,
|
||||||
|
uiChatItemRoundness: 0.75,
|
||||||
|
uiChatItemTail: true,
|
||||||
uiColorScheme: DefaultTheme.SYSTEM_THEME_NAME,
|
uiColorScheme: DefaultTheme.SYSTEM_THEME_NAME,
|
||||||
uiDarkColorScheme: DefaultTheme.SIMPLEX.themeName,
|
uiDarkColorScheme: DefaultTheme.SIMPLEX.themeName,
|
||||||
uiCurrentThemeIds: nil as [String: String]?,
|
uiCurrentThemeIds: nil as [String: String]?,
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public func registerGroupDefaults() {
|
|||||||
GROUP_DEFAULT_NTF_ENABLE_LOCAL: false,
|
GROUP_DEFAULT_NTF_ENABLE_LOCAL: false,
|
||||||
GROUP_DEFAULT_NTF_ENABLE_PERIODIC: false,
|
GROUP_DEFAULT_NTF_ENABLE_PERIODIC: false,
|
||||||
GROUP_DEFAULT_NETWORK_USE_ONION_HOSTS: OnionHosts.no.rawValue,
|
GROUP_DEFAULT_NETWORK_USE_ONION_HOSTS: OnionHosts.no.rawValue,
|
||||||
GROUP_DEFAULT_NETWORK_SESSION_MODE: TransportSessionMode.user.rawValue,
|
GROUP_DEFAULT_NETWORK_SESSION_MODE: TransportSessionMode.session.rawValue,
|
||||||
GROUP_DEFAULT_NETWORK_SMP_PROXY_MODE: SMPProxyMode.unknown.rawValue,
|
GROUP_DEFAULT_NETWORK_SMP_PROXY_MODE: SMPProxyMode.unknown.rawValue,
|
||||||
GROUP_DEFAULT_NETWORK_SMP_PROXY_FALLBACK: SMPProxyFallback.allowProtected.rawValue,
|
GROUP_DEFAULT_NETWORK_SMP_PROXY_FALLBACK: SMPProxyFallback.allowProtected.rawValue,
|
||||||
GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT: NetCfg.defaults.tcpConnectTimeout,
|
GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT: NetCfg.defaults.tcpConnectTimeout,
|
||||||
@@ -85,7 +85,7 @@ public func registerGroupDefaults() {
|
|||||||
GROUP_DEFAULT_INITIAL_RANDOM_DB_PASSPHRASE: false,
|
GROUP_DEFAULT_INITIAL_RANDOM_DB_PASSPHRASE: false,
|
||||||
GROUP_DEFAULT_APP_LOCAL_AUTH_ENABLED: true,
|
GROUP_DEFAULT_APP_LOCAL_AUTH_ENABLED: true,
|
||||||
GROUP_DEFAULT_ALLOW_SHARE_EXTENSION: false,
|
GROUP_DEFAULT_ALLOW_SHARE_EXTENSION: false,
|
||||||
GROUP_DEFAULT_PRIVACY_LINK_PREVIEWS: false,
|
GROUP_DEFAULT_PRIVACY_LINK_PREVIEWS: true,
|
||||||
GROUP_DEFAULT_PRIVACY_ACCEPT_IMAGES: true,
|
GROUP_DEFAULT_PRIVACY_ACCEPT_IMAGES: true,
|
||||||
GROUP_DEFAULT_PRIVACY_TRANSFER_IMAGES_INLINE: false,
|
GROUP_DEFAULT_PRIVACY_TRANSFER_IMAGES_INLINE: false,
|
||||||
GROUP_DEFAULT_PRIVACY_ENCRYPT_LOCAL_FILES: true,
|
GROUP_DEFAULT_PRIVACY_ENCRYPT_LOCAL_FILES: true,
|
||||||
@@ -232,7 +232,7 @@ public let networkUseOnionHostsGroupDefault = EnumDefault<OnionHosts>(
|
|||||||
public let networkSessionModeGroupDefault = EnumDefault<TransportSessionMode>(
|
public let networkSessionModeGroupDefault = EnumDefault<TransportSessionMode>(
|
||||||
defaults: groupDefaults,
|
defaults: groupDefaults,
|
||||||
forKey: GROUP_DEFAULT_NETWORK_SESSION_MODE,
|
forKey: GROUP_DEFAULT_NETWORK_SESSION_MODE,
|
||||||
withDefault: .user
|
withDefault: .session
|
||||||
)
|
)
|
||||||
|
|
||||||
public let networkSMPProxyModeGroupDefault = EnumDefault<SMPProxyMode>(
|
public let networkSMPProxyModeGroupDefault = EnumDefault<SMPProxyMode>(
|
||||||
@@ -357,6 +357,7 @@ public func getNetCfg() -> NetCfg {
|
|||||||
sessionMode: sessionMode,
|
sessionMode: sessionMode,
|
||||||
smpProxyMode: smpProxyMode,
|
smpProxyMode: smpProxyMode,
|
||||||
smpProxyFallback: smpProxyFallback,
|
smpProxyFallback: smpProxyFallback,
|
||||||
|
smpWebPort: false,
|
||||||
tcpConnectTimeout: tcpConnectTimeout,
|
tcpConnectTimeout: tcpConnectTimeout,
|
||||||
tcpTimeout: tcpTimeout,
|
tcpTimeout: tcpTimeout,
|
||||||
tcpTimeoutPerKb: tcpTimeoutPerKb,
|
tcpTimeoutPerKb: tcpTimeoutPerKb,
|
||||||
|
|||||||
@@ -80,6 +80,14 @@ public enum CallMediaType: String, Codable, Equatable {
|
|||||||
case audio = "audio"
|
case audio = "audio"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum CallMediaSource: String, Codable, Equatable {
|
||||||
|
case mic = "mic"
|
||||||
|
case camera = "camera"
|
||||||
|
case screenAudio = "screenAudio"
|
||||||
|
case screenVideo = "screenVideo"
|
||||||
|
case unknown = "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
public enum VideoCamera: String, Codable, Equatable {
|
public enum VideoCamera: String, Codable, Equatable {
|
||||||
case user = "user"
|
case user = "user"
|
||||||
case environment = "environment"
|
case environment = "environment"
|
||||||
|
|||||||
@@ -1852,6 +1852,7 @@ public struct PendingContactConnection: Decodable, NamedChat, Hashable {
|
|||||||
|
|
||||||
public enum ConnStatus: String, Decodable, Hashable {
|
public enum ConnStatus: String, Decodable, Hashable {
|
||||||
case new = "new"
|
case new = "new"
|
||||||
|
case prepared = "prepared"
|
||||||
case joined = "joined"
|
case joined = "joined"
|
||||||
case requested = "requested"
|
case requested = "requested"
|
||||||
case accepted = "accepted"
|
case accepted = "accepted"
|
||||||
@@ -1863,6 +1864,7 @@ public enum ConnStatus: String, Decodable, Hashable {
|
|||||||
get {
|
get {
|
||||||
switch self {
|
switch self {
|
||||||
case .new: return true
|
case .new: return true
|
||||||
|
case .prepared: return false
|
||||||
case .joined: return false
|
case .joined: return false
|
||||||
case .requested: return true
|
case .requested: return true
|
||||||
case .accepted: return true
|
case .accepted: return true
|
||||||
@@ -2240,41 +2242,53 @@ public struct MemberSubError: Decodable, Hashable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum ConnectionEntity: Decodable, Hashable {
|
public enum ConnectionEntity: Decodable, Hashable {
|
||||||
case rcvDirectMsgConnection(contact: Contact?)
|
case rcvDirectMsgConnection(entityConnection: Connection, contact: Contact?)
|
||||||
case rcvGroupMsgConnection(groupInfo: GroupInfo, groupMember: GroupMember)
|
case rcvGroupMsgConnection(entityConnection: Connection, groupInfo: GroupInfo, groupMember: GroupMember)
|
||||||
case sndFileConnection(sndFileTransfer: SndFileTransfer)
|
case sndFileConnection(entityConnection: Connection, sndFileTransfer: SndFileTransfer)
|
||||||
case rcvFileConnection(rcvFileTransfer: RcvFileTransfer)
|
case rcvFileConnection(entityConnection: Connection, rcvFileTransfer: RcvFileTransfer)
|
||||||
case userContactConnection(userContact: UserContact)
|
case userContactConnection(entityConnection: Connection, userContact: UserContact)
|
||||||
|
|
||||||
public var id: String? {
|
public var id: String? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .rcvDirectMsgConnection(contact):
|
case let .rcvDirectMsgConnection(_, contact):
|
||||||
return contact?.id
|
return contact?.id
|
||||||
case let .rcvGroupMsgConnection(_, groupMember):
|
case let .rcvGroupMsgConnection(_, _, groupMember):
|
||||||
return groupMember.id
|
return groupMember.id
|
||||||
case let .userContactConnection(userContact):
|
case let .userContactConnection(_, userContact):
|
||||||
return userContact.id
|
return userContact.id
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public var ntfsEnabled: Bool {
|
public var conn: Connection {
|
||||||
switch self {
|
switch self {
|
||||||
case let .rcvDirectMsgConnection(contact): return contact?.chatSettings.enableNtfs == .all
|
case let .rcvDirectMsgConnection(entityConnection, _): entityConnection
|
||||||
case let .rcvGroupMsgConnection(groupInfo, _): return groupInfo.chatSettings.enableNtfs == .all
|
case let .rcvGroupMsgConnection(entityConnection, _, _): entityConnection
|
||||||
case .sndFileConnection: return false
|
case let .sndFileConnection(entityConnection, _): entityConnection
|
||||||
case .rcvFileConnection: return false
|
case let .rcvFileConnection(entityConnection, _): entityConnection
|
||||||
case let .userContactConnection(userContact): return userContact.groupId == nil
|
case let .userContactConnection(entityConnection, _): entityConnection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct NtfConn: Decodable, Hashable {
|
||||||
|
public var user_: User?
|
||||||
|
public var connEntity_: ConnectionEntity?
|
||||||
|
public var expectedMsg_: NtfMsgInfo?
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public struct NtfMsgInfo: Decodable, Hashable {
|
public struct NtfMsgInfo: Decodable, Hashable {
|
||||||
public var msgId: String
|
public var msgId: String
|
||||||
public var msgTs: Date
|
public var msgTs: Date
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct NtfMsgAckInfo: Decodable, Hashable {
|
||||||
|
public var msgId: String
|
||||||
|
public var msgTs_: Date?
|
||||||
|
}
|
||||||
|
|
||||||
public struct ChatItemDeletion: Decodable, Hashable {
|
public struct ChatItemDeletion: Decodable, Hashable {
|
||||||
public var deletedChatItem: AChatItem
|
public var deletedChatItem: AChatItem
|
||||||
public var toChatItem: AChatItem? = nil
|
public var toChatItem: AChatItem? = nil
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ public func resizeImageToDataSize(_ image: UIImage, maxDataSize: Int64, hasAlpha
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
public func resizeImageToStrSize(_ image: UIImage, maxDataSize: Int64) -> String? {
|
public func resizeImageToStrSizeSync(_ image: UIImage, maxDataSize: Int64) -> String? {
|
||||||
var img = image
|
var img = image
|
||||||
let hasAlpha = imageHasAlpha(image)
|
let hasAlpha = imageHasAlpha(image)
|
||||||
var str = compressImageStr(img, hasAlpha: hasAlpha)
|
var str = compressImageStr(img, hasAlpha: hasAlpha)
|
||||||
@@ -116,7 +116,15 @@ public func resizeImageToStrSize(_ image: UIImage, maxDataSize: Int64) -> String
|
|||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func resizeImageToStrSize(_ image: UIImage, maxDataSize: Int64) async -> String? {
|
||||||
|
resizeImageToStrSizeSync(image, maxDataSize: maxDataSize)
|
||||||
|
}
|
||||||
|
|
||||||
public func compressImageStr(_ image: UIImage, _ compressionQuality: CGFloat = 0.85, hasAlpha: Bool) -> String? {
|
public func compressImageStr(_ image: UIImage, _ compressionQuality: CGFloat = 0.85, hasAlpha: Bool) -> String? {
|
||||||
|
// // Heavy workload to verify if UI gets blocked by the call
|
||||||
|
// for i in 0..<100 {
|
||||||
|
// print(image.jpegData(compressionQuality: Double(i) / 100)?.count ?? 0, terminator: ", ")
|
||||||
|
// }
|
||||||
let ext = hasAlpha ? "png" : "jpg"
|
let ext = hasAlpha ? "png" : "jpg"
|
||||||
if let data = hasAlpha ? image.pngData() : image.jpegData(compressionQuality: compressionQuality) {
|
if let data = hasAlpha ? image.pngData() : image.jpegData(compressionQuality: compressionQuality) {
|
||||||
return "data:image/\(ext);base64,\(data.base64EncodedString())"
|
return "data:image/\(ext);base64,\(data.base64EncodedString())"
|
||||||
@@ -426,7 +434,7 @@ public func getLinkPreview(url: URL, cb: @escaping (LinkPreview?) -> Void) {
|
|||||||
logger.error("Couldn't load image preview from link metadata with error: \(error.localizedDescription)")
|
logger.error("Couldn't load image preview from link metadata with error: \(error.localizedDescription)")
|
||||||
} else {
|
} else {
|
||||||
if let image = object as? UIImage,
|
if let image = object as? UIImage,
|
||||||
let resized = resizeImageToStrSize(image, maxDataSize: 14000),
|
let resized = resizeImageToStrSizeSync(image, maxDataSize: 14000),
|
||||||
let title = metadata.title,
|
let title = metadata.title,
|
||||||
let uri = metadata.originalURL {
|
let uri = metadata.originalURL {
|
||||||
linkPreview = LinkPreview(uri: uri, title: title, image: resized)
|
linkPreview = LinkPreview(uri: uri, title: title, image: resized)
|
||||||
|
|||||||
@@ -15,13 +15,14 @@ public let ntfCategoryContactConnected = "NTF_CAT_CONTACT_CONNECTED"
|
|||||||
public let ntfCategoryMessageReceived = "NTF_CAT_MESSAGE_RECEIVED"
|
public let ntfCategoryMessageReceived = "NTF_CAT_MESSAGE_RECEIVED"
|
||||||
public let ntfCategoryCallInvitation = "NTF_CAT_CALL_INVITATION"
|
public let ntfCategoryCallInvitation = "NTF_CAT_CALL_INVITATION"
|
||||||
public let ntfCategoryConnectionEvent = "NTF_CAT_CONNECTION_EVENT"
|
public let ntfCategoryConnectionEvent = "NTF_CAT_CONNECTION_EVENT"
|
||||||
|
public let ntfCategoryManyEvents = "NTF_CAT_MANY_EVENTS"
|
||||||
public let ntfCategoryCheckMessage = "NTF_CAT_CHECK_MESSAGE"
|
public let ntfCategoryCheckMessage = "NTF_CAT_CHECK_MESSAGE"
|
||||||
|
|
||||||
public let appNotificationId = "chat.simplex.app.notification"
|
public let appNotificationId = "chat.simplex.app.notification"
|
||||||
|
|
||||||
let contactHidden = NSLocalizedString("Contact hidden:", comment: "notification")
|
let contactHidden = NSLocalizedString("Contact hidden:", comment: "notification")
|
||||||
|
|
||||||
public func createContactRequestNtf(_ user: any UserLike, _ contactRequest: UserContactRequest) -> UNMutableNotificationContent {
|
public func createContactRequestNtf(_ user: any UserLike, _ contactRequest: UserContactRequest, _ badgeCount: Int) -> UNMutableNotificationContent {
|
||||||
let hideContent = ntfPreviewModeGroupDefault.get() == .hidden
|
let hideContent = ntfPreviewModeGroupDefault.get() == .hidden
|
||||||
return createNotification(
|
return createNotification(
|
||||||
categoryIdentifier: ntfCategoryContactRequest,
|
categoryIdentifier: ntfCategoryContactRequest,
|
||||||
@@ -34,11 +35,12 @@ public func createContactRequestNtf(_ user: any UserLike, _ contactRequest: User
|
|||||||
hideContent ? NSLocalizedString("this contact", comment: "notification title") : contactRequest.chatViewName
|
hideContent ? NSLocalizedString("this contact", comment: "notification title") : contactRequest.chatViewName
|
||||||
),
|
),
|
||||||
targetContentIdentifier: nil,
|
targetContentIdentifier: nil,
|
||||||
userInfo: ["chatId": contactRequest.id, "contactRequestId": contactRequest.apiId, "userId": user.userId]
|
userInfo: ["chatId": contactRequest.id, "contactRequestId": contactRequest.apiId, "userId": user.userId],
|
||||||
|
badgeCount: badgeCount
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func createContactConnectedNtf(_ user: any UserLike, _ contact: Contact) -> UNMutableNotificationContent {
|
public func createContactConnectedNtf(_ user: any UserLike, _ contact: Contact, _ badgeCount: Int) -> UNMutableNotificationContent {
|
||||||
let hideContent = ntfPreviewModeGroupDefault.get() == .hidden
|
let hideContent = ntfPreviewModeGroupDefault.get() == .hidden
|
||||||
return createNotification(
|
return createNotification(
|
||||||
categoryIdentifier: ntfCategoryContactConnected,
|
categoryIdentifier: ntfCategoryContactConnected,
|
||||||
@@ -51,12 +53,13 @@ public func createContactConnectedNtf(_ user: any UserLike, _ contact: Contact)
|
|||||||
hideContent ? NSLocalizedString("this contact", comment: "notification title") : contact.chatViewName
|
hideContent ? NSLocalizedString("this contact", comment: "notification title") : contact.chatViewName
|
||||||
),
|
),
|
||||||
targetContentIdentifier: contact.id,
|
targetContentIdentifier: contact.id,
|
||||||
userInfo: ["userId": user.userId]
|
userInfo: ["userId": user.userId],
|
||||||
// userInfo: ["chatId": contact.id, "contactId": contact.apiId]
|
// userInfo: ["chatId": contact.id, "contactId": contact.apiId]
|
||||||
|
badgeCount: badgeCount
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func createMessageReceivedNtf(_ user: any UserLike, _ cInfo: ChatInfo, _ cItem: ChatItem) -> UNMutableNotificationContent {
|
public func createMessageReceivedNtf(_ user: any UserLike, _ cInfo: ChatInfo, _ cItem: ChatItem, _ badgeCount: Int) -> UNMutableNotificationContent {
|
||||||
let previewMode = ntfPreviewModeGroupDefault.get()
|
let previewMode = ntfPreviewModeGroupDefault.get()
|
||||||
var title: String
|
var title: String
|
||||||
if case let .group(groupInfo) = cInfo, case let .groupRcv(groupMember) = cItem.chatDir {
|
if case let .group(groupInfo) = cInfo, case let .groupRcv(groupMember) = cItem.chatDir {
|
||||||
@@ -69,12 +72,13 @@ public func createMessageReceivedNtf(_ user: any UserLike, _ cInfo: ChatInfo, _
|
|||||||
title: title,
|
title: title,
|
||||||
body: previewMode == .message ? hideSecrets(cItem) : NSLocalizedString("new message", comment: "notification"),
|
body: previewMode == .message ? hideSecrets(cItem) : NSLocalizedString("new message", comment: "notification"),
|
||||||
targetContentIdentifier: cInfo.id,
|
targetContentIdentifier: cInfo.id,
|
||||||
userInfo: ["userId": user.userId]
|
userInfo: ["userId": user.userId],
|
||||||
// userInfo: ["chatId": cInfo.id, "chatItemId": cItem.id]
|
// userInfo: ["chatId": cInfo.id, "chatItemId": cItem.id]
|
||||||
|
badgeCount: badgeCount
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func createCallInvitationNtf(_ invitation: RcvCallInvitation) -> UNMutableNotificationContent {
|
public func createCallInvitationNtf(_ invitation: RcvCallInvitation, _ badgeCount: Int) -> UNMutableNotificationContent {
|
||||||
let text = invitation.callType.media == .video
|
let text = invitation.callType.media == .video
|
||||||
? NSLocalizedString("Incoming video call", comment: "notification")
|
? NSLocalizedString("Incoming video call", comment: "notification")
|
||||||
: NSLocalizedString("Incoming audio call", comment: "notification")
|
: NSLocalizedString("Incoming audio call", comment: "notification")
|
||||||
@@ -84,17 +88,18 @@ public func createCallInvitationNtf(_ invitation: RcvCallInvitation) -> UNMutabl
|
|||||||
title: hideContent ? contactHidden : "\(invitation.contact.chatViewName):",
|
title: hideContent ? contactHidden : "\(invitation.contact.chatViewName):",
|
||||||
body: text,
|
body: text,
|
||||||
targetContentIdentifier: nil,
|
targetContentIdentifier: nil,
|
||||||
userInfo: ["chatId": invitation.contact.id, "userId": invitation.user.userId]
|
userInfo: ["chatId": invitation.contact.id, "userId": invitation.user.userId],
|
||||||
|
badgeCount: badgeCount
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func createConnectionEventNtf(_ user: User, _ connEntity: ConnectionEntity) -> UNMutableNotificationContent {
|
public func createConnectionEventNtf(_ user: User, _ connEntity: ConnectionEntity, _ badgeCount: Int) -> UNMutableNotificationContent {
|
||||||
let hideContent = ntfPreviewModeGroupDefault.get() == .hidden
|
let hideContent = ntfPreviewModeGroupDefault.get() == .hidden
|
||||||
var title: String
|
var title: String
|
||||||
var body: String? = nil
|
var body: String? = nil
|
||||||
var targetContentIdentifier: String? = nil
|
var targetContentIdentifier: String? = nil
|
||||||
switch connEntity {
|
switch connEntity {
|
||||||
case let .rcvDirectMsgConnection(contact):
|
case let .rcvDirectMsgConnection(_, contact):
|
||||||
if let contact = contact {
|
if let contact = contact {
|
||||||
title = hideContent ? contactHidden : "\(contact.chatViewName):"
|
title = hideContent ? contactHidden : "\(contact.chatViewName):"
|
||||||
targetContentIdentifier = contact.id
|
targetContentIdentifier = contact.id
|
||||||
@@ -102,7 +107,7 @@ public func createConnectionEventNtf(_ user: User, _ connEntity: ConnectionEntit
|
|||||||
title = NSLocalizedString("New contact:", comment: "notification")
|
title = NSLocalizedString("New contact:", comment: "notification")
|
||||||
}
|
}
|
||||||
body = NSLocalizedString("message received", comment: "notification")
|
body = NSLocalizedString("message received", comment: "notification")
|
||||||
case let .rcvGroupMsgConnection(groupInfo, groupMember):
|
case let .rcvGroupMsgConnection(_, groupInfo, groupMember):
|
||||||
title = groupMsgNtfTitle(groupInfo, groupMember, hideContent: hideContent)
|
title = groupMsgNtfTitle(groupInfo, groupMember, hideContent: hideContent)
|
||||||
body = NSLocalizedString("message received", comment: "notification")
|
body = NSLocalizedString("message received", comment: "notification")
|
||||||
targetContentIdentifier = groupInfo.id
|
targetContentIdentifier = groupInfo.id
|
||||||
@@ -118,11 +123,12 @@ public func createConnectionEventNtf(_ user: User, _ connEntity: ConnectionEntit
|
|||||||
title: title,
|
title: title,
|
||||||
body: body,
|
body: body,
|
||||||
targetContentIdentifier: targetContentIdentifier,
|
targetContentIdentifier: targetContentIdentifier,
|
||||||
userInfo: ["userId": user.userId]
|
userInfo: ["userId": user.userId],
|
||||||
|
badgeCount: badgeCount
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func createErrorNtf(_ dbStatus: DBMigrationResult) -> UNMutableNotificationContent {
|
public func createErrorNtf(_ dbStatus: DBMigrationResult, _ badgeCount: Int) -> UNMutableNotificationContent {
|
||||||
var title: String
|
var title: String
|
||||||
switch dbStatus {
|
switch dbStatus {
|
||||||
case .errorNotADatabase:
|
case .errorNotADatabase:
|
||||||
@@ -142,14 +148,16 @@ public func createErrorNtf(_ dbStatus: DBMigrationResult) -> UNMutableNotificati
|
|||||||
}
|
}
|
||||||
return createNotification(
|
return createNotification(
|
||||||
categoryIdentifier: ntfCategoryConnectionEvent,
|
categoryIdentifier: ntfCategoryConnectionEvent,
|
||||||
title: title
|
title: title,
|
||||||
|
badgeCount: badgeCount
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func createAppStoppedNtf() -> UNMutableNotificationContent {
|
public func createAppStoppedNtf(_ badgeCount: Int) -> UNMutableNotificationContent {
|
||||||
return createNotification(
|
return createNotification(
|
||||||
categoryIdentifier: ntfCategoryConnectionEvent,
|
categoryIdentifier: ntfCategoryConnectionEvent,
|
||||||
title: NSLocalizedString("Encrypted message: app is stopped", comment: "notification")
|
title: NSLocalizedString("Encrypted message: app is stopped", comment: "notification"),
|
||||||
|
badgeCount: badgeCount
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,8 +167,15 @@ private func groupMsgNtfTitle(_ groupInfo: GroupInfo, _ groupMember: GroupMember
|
|||||||
: "#\(groupInfo.displayName) \(groupMember.chatViewName):"
|
: "#\(groupInfo.displayName) \(groupMember.chatViewName):"
|
||||||
}
|
}
|
||||||
|
|
||||||
public func createNotification(categoryIdentifier: String, title: String, subtitle: String? = nil, body: String? = nil,
|
public func createNotification(
|
||||||
targetContentIdentifier: String? = nil, userInfo: [AnyHashable : Any] = [:]) -> UNMutableNotificationContent {
|
categoryIdentifier: String,
|
||||||
|
title: String,
|
||||||
|
subtitle: String? = nil,
|
||||||
|
body: String? = nil,
|
||||||
|
targetContentIdentifier: String? = nil,
|
||||||
|
userInfo: [AnyHashable : Any] = [:],
|
||||||
|
badgeCount: Int
|
||||||
|
) -> UNMutableNotificationContent {
|
||||||
let content = UNMutableNotificationContent()
|
let content = UNMutableNotificationContent()
|
||||||
content.categoryIdentifier = categoryIdentifier
|
content.categoryIdentifier = categoryIdentifier
|
||||||
content.title = title
|
content.title = title
|
||||||
@@ -170,6 +185,7 @@ public func createNotification(categoryIdentifier: String, title: String, subtit
|
|||||||
content.userInfo = userInfo
|
content.userInfo = userInfo
|
||||||
// TODO move logic of adding sound here, so it applies to background notifications too
|
// TODO move logic of adding sound here, so it applies to background notifications too
|
||||||
content.sound = .default
|
content.sound = .default
|
||||||
|
content.badge = badgeCount as NSNumber
|
||||||
// content.interruptionLevel = .active
|
// content.interruptionLevel = .active
|
||||||
// content.relevanceScore = 0.5 // 0-1
|
// content.relevanceScore = 0.5 // 0-1
|
||||||
return content
|
return content
|
||||||
|
|||||||
@@ -791,6 +791,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chat preferences" = "Чат настройки";
|
"Chat preferences" = "Чат настройки";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Chat profile" = "Потребителски профил";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chats" = "Чатове";
|
"Chats" = "Чатове";
|
||||||
|
|
||||||
@@ -1732,7 +1735,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error stopping chat" = "Грешка при спиране на чата";
|
"Error stopping chat" = "Грешка при спиране на чата";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* alertTitle */
|
||||||
"Error switching profile!" = "Грешка при смяна на профил!";
|
"Error switching profile!" = "Грешка при смяна на профил!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -1759,8 +1762,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error: " = "Грешка: ";
|
"Error: " = "Грешка: ";
|
||||||
|
|
||||||
/* file error text
|
/* alert message */
|
||||||
snd error text */
|
|
||||||
"Error: %@" = "Грешка: %@";
|
"Error: %@" = "Грешка: %@";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -3990,9 +3992,6 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Use the app while in the call." = "Използвайте приложението по време на разговора.";
|
"Use the app while in the call." = "Използвайте приложението по време на разговора.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"User profile" = "Потребителски профил";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Using SimpleX Chat servers." = "Използват се сървърите на SimpleX Chat.";
|
"Using SimpleX Chat servers." = "Използват се сървърите на SimpleX Chat.";
|
||||||
|
|
||||||
@@ -4167,9 +4166,6 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"you" = "вие";
|
"you" = "вие";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"You" = "Вие";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"You **must not** use the same database on two devices." = "**Не трябва** да използвате една и съща база данни на две устройства.";
|
"You **must not** use the same database on two devices." = "**Не трябва** да използвате една и съща база данни на две устройства.";
|
||||||
|
|
||||||
|
|||||||
@@ -644,6 +644,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chat preferences" = "Předvolby chatu";
|
"Chat preferences" = "Předvolby chatu";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Chat profile" = "Profil uživatele";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chats" = "Chaty";
|
"Chats" = "Chaty";
|
||||||
|
|
||||||
@@ -1422,7 +1425,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error stopping chat" = "Chyba při zastavení chatu";
|
"Error stopping chat" = "Chyba při zastavení chatu";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* alertTitle */
|
||||||
"Error switching profile!" = "Chyba při přepínání profilu!";
|
"Error switching profile!" = "Chyba při přepínání profilu!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -1443,8 +1446,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error: " = "Chyba: ";
|
"Error: " = "Chyba: ";
|
||||||
|
|
||||||
/* file error text
|
/* alert message */
|
||||||
snd error text */
|
|
||||||
"Error: %@" = "Chyba: %@";
|
"Error: %@" = "Chyba: %@";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -3230,9 +3232,6 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Use SimpleX Chat servers?" = "Používat servery SimpleX Chat?";
|
"Use SimpleX Chat servers?" = "Používat servery SimpleX Chat?";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"User profile" = "Profil uživatele";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Using SimpleX Chat servers." = "Používat servery SimpleX Chat.";
|
"Using SimpleX Chat servers." = "Používat servery SimpleX Chat.";
|
||||||
|
|
||||||
@@ -3350,9 +3349,6 @@
|
|||||||
/* pref value */
|
/* pref value */
|
||||||
"yes" = "ano";
|
"yes" = "ano";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"You" = "Vy";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"You accepted connection" = "Přijali jste spojení";
|
"You accepted connection" = "Přijali jste spojení";
|
||||||
|
|
||||||
|
|||||||
@@ -175,9 +175,24 @@
|
|||||||
/* time interval */
|
/* time interval */
|
||||||
"%d days" = "%d Tage";
|
"%d days" = "%d Tage";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) are still being downloaded." = "%d Datei(en) wird/werden immer noch heruntergeladen.";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) failed to download." = "Bei %d Datei(en) ist das Herunterladen fehlgeschlagen.";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) were deleted." = "%d Datei(en) wurde(n) gelöscht.";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) were not downloaded." = "%d Datei(en) wurde(n) nicht heruntergeladen.";
|
||||||
|
|
||||||
/* time interval */
|
/* time interval */
|
||||||
"%d hours" = "%d Stunden";
|
"%d hours" = "%d Stunden";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"%d messages not forwarded" = "%d Nachrichten wurden nicht weitergeleitet";
|
||||||
|
|
||||||
/* time interval */
|
/* time interval */
|
||||||
"%d min" = "%d min";
|
"%d min" = "%d min";
|
||||||
|
|
||||||
@@ -457,7 +472,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"All new messages from %@ will be hidden!" = "Von %@ werden alle neuen Nachrichten ausgeblendet!";
|
"All new messages from %@ will be hidden!" = "Von %@ werden alle neuen Nachrichten ausgeblendet!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* profile dropdown */
|
||||||
"All profiles" = "Alle Profile";
|
"All profiles" = "Alle Profile";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -580,6 +595,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"App passcode is replaced with self-destruct passcode." = "App-Zugangscode wurde durch den Selbstzerstörungs-Zugangscode ersetzt.";
|
"App passcode is replaced with self-destruct passcode." = "App-Zugangscode wurde durch den Selbstzerstörungs-Zugangscode ersetzt.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"App session" = "App-Sitzung";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"App version" = "App Version";
|
"App version" = "App Version";
|
||||||
|
|
||||||
@@ -676,15 +694,30 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Bad message ID" = "Falsche Nachrichten-ID";
|
"Bad message ID" = "Falsche Nachrichten-ID";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better calls" = "Verbesserte Anrufe";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Better groups" = "Bessere Gruppen";
|
"Better groups" = "Bessere Gruppen";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better message dates." = "Verbesserte Nachrichten-Datumsinformation";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Better messages" = "Verbesserungen bei Nachrichten";
|
"Better messages" = "Verbesserungen bei Nachrichten";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Better networking" = "Kontrollieren Sie Ihr Netzwerk";
|
"Better networking" = "Kontrollieren Sie Ihr Netzwerk";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better notifications" = "Verbesserte Benachrichtigungen";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better security ✅" = "Verbesserte Sicherheit ✅";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better user experience" = "Verbesserte Nutzer-Erfahrung";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Black" = "Schwarz";
|
"Black" = "Schwarz";
|
||||||
|
|
||||||
@@ -899,6 +932,9 @@
|
|||||||
/* alert message */
|
/* alert message */
|
||||||
"Chat preferences were changed." = "Die Chat-Präferenzen wurden geändert.";
|
"Chat preferences were changed." = "Die Chat-Präferenzen wurden geändert.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Chat profile" = "Benutzerprofil";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chat theme" = "Chat-Design";
|
"Chat theme" = "Chat-Design";
|
||||||
|
|
||||||
@@ -1188,7 +1224,7 @@
|
|||||||
"Core version: v%@" = "Core Version: v%@";
|
"Core version: v%@" = "Core Version: v%@";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Corner" = "Ecke";
|
"Corner" = "Abrundung Ecken";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Correct name to %@?" = "Richtiger Name für %@?";
|
"Correct name to %@?" = "Richtiger Name für %@?";
|
||||||
@@ -1271,6 +1307,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Custom time" = "Zeit anpassen";
|
"Custom time" = "Zeit anpassen";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Customizable message shape." = "Anpassbares Format des Nachrichtenfelds";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Customize theme" = "Design anpassen";
|
"Customize theme" = "Design anpassen";
|
||||||
|
|
||||||
@@ -1461,6 +1500,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Delete old database?" = "Alte Datenbank löschen?";
|
"Delete old database?" = "Alte Datenbank löschen?";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Delete or moderate up to 200 messages." = "Bis zu 200 Nachrichten löschen oder moderieren";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Delete pending connection?" = "Ausstehende Verbindung löschen?";
|
"Delete pending connection?" = "Ausstehende Verbindung löschen?";
|
||||||
|
|
||||||
@@ -1623,6 +1665,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Do NOT send messages directly, even if your or destination server does not support private routing." = "Nachrichten werden nicht direkt versendet, selbst wenn Ihr oder der Zielserver kein privates Routing unterstützt.";
|
"Do NOT send messages directly, even if your or destination server does not support private routing." = "Nachrichten werden nicht direkt versendet, selbst wenn Ihr oder der Zielserver kein privates Routing unterstützt.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Do not use credentials with proxy." = "Verwenden Sie keine Anmeldeinformationen mit einem Proxy.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Do NOT use private routing." = "Sie nutzen KEIN privates Routing.";
|
"Do NOT use private routing." = "Sie nutzen KEIN privates Routing.";
|
||||||
|
|
||||||
@@ -1654,6 +1699,9 @@
|
|||||||
/* server test step */
|
/* server test step */
|
||||||
"Download file" = "Datei herunterladen";
|
"Download file" = "Datei herunterladen";
|
||||||
|
|
||||||
|
/* alert action */
|
||||||
|
"Download files" = "Dateien herunterladen";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Downloaded" = "Heruntergeladen";
|
"Downloaded" = "Heruntergeladen";
|
||||||
|
|
||||||
@@ -2020,7 +2068,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error switching profile" = "Fehler beim Wechseln des Profils";
|
"Error switching profile" = "Fehler beim Wechseln des Profils";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* alertTitle */
|
||||||
"Error switching profile!" = "Fehler beim Umschalten des Profils!";
|
"Error switching profile!" = "Fehler beim Umschalten des Profils!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -2047,8 +2095,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error: " = "Fehler: ";
|
"Error: " = "Fehler: ";
|
||||||
|
|
||||||
/* file error text
|
/* alert message */
|
||||||
snd error text */
|
|
||||||
"Error: %@" = "Fehler: %@";
|
"Error: %@" = "Fehler: %@";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -2073,7 +2120,7 @@
|
|||||||
"Expand" = "Erweitern";
|
"Expand" = "Erweitern";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"expired" = "abgelaufen";
|
"expired" = "Abgelaufen";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Export database" = "Datenbank exportieren";
|
"Export database" = "Datenbank exportieren";
|
||||||
@@ -2108,6 +2155,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"File error" = "Datei-Fehler";
|
"File error" = "Datei-Fehler";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"File errors:\n%@" = "Datei-Fehler:\n%@";
|
||||||
|
|
||||||
/* file error text */
|
/* file error text */
|
||||||
"File not found - most likely file was deleted or cancelled." = "Datei nicht gefunden - höchstwahrscheinlich wurde die Datei gelöscht oder der Transfer abgebrochen.";
|
"File not found - most likely file was deleted or cancelled." = "Datei nicht gefunden - höchstwahrscheinlich wurde die Datei gelöscht oder der Transfer abgebrochen.";
|
||||||
|
|
||||||
@@ -2189,9 +2239,21 @@
|
|||||||
/* chat item action */
|
/* chat item action */
|
||||||
"Forward" = "Weiterleiten";
|
"Forward" = "Weiterleiten";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Forward %d message(s)?" = "%d Nachricht(en) weiterleiten?";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Forward and save messages" = "Nachrichten weiterleiten und speichern";
|
"Forward and save messages" = "Nachrichten weiterleiten und speichern";
|
||||||
|
|
||||||
|
/* alert action */
|
||||||
|
"Forward messages" = "Nachrichten weiterleiten";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Forward messages without files?" = "Nachrichten ohne Dateien weiterleiten?";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Forward up to 20 messages at once." = "Bis zu 20 Nachrichten auf einmal weiterleiten";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"forwarded" = "weitergeleitet";
|
"forwarded" = "weitergeleitet";
|
||||||
|
|
||||||
@@ -2201,6 +2263,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Forwarded from" = "Weitergeleitet aus";
|
"Forwarded from" = "Weitergeleitet aus";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Forwarding %lld messages" = "%lld Nachricht(en) wird/werden weitergeleitet";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Forwarding server %@ failed to connect to destination server %@. Please try later." = "Weiterleitungsserver %@ konnte sich nicht mit dem Zielserver %@ verbinden. Bitte versuchen Sie es später erneut.";
|
"Forwarding server %@ failed to connect to destination server %@. Please try later." = "Weiterleitungsserver %@ konnte sich nicht mit dem Zielserver %@ verbinden. Bitte versuchen Sie es später erneut.";
|
||||||
|
|
||||||
@@ -2429,6 +2494,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Importing archive" = "Archiv wird importiert";
|
"Importing archive" = "Archiv wird importiert";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Improved delivery, reduced traffic usage.\nMore improvements are coming soon!" = "Verbesserte Nachrichten-Auslieferung und verringerter Datenverbrauch.\nWeitere Verbesserungen sind bald verfügbar!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Improved message delivery" = "Verbesserte Zustellung von Nachrichten";
|
"Improved message delivery" = "Verbesserte Zustellung von Nachrichten";
|
||||||
|
|
||||||
@@ -2588,6 +2656,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "Für die sichere Speicherung des Passworts nach dem Neustart der App und dem Wechsel des Passworts wird der iOS Schlüsselbund verwendet - dies erlaubt den Empfang von Push-Benachrichtigungen.";
|
"iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "Für die sichere Speicherung des Passworts nach dem Neustart der App und dem Wechsel des Passworts wird der iOS Schlüsselbund verwendet - dies erlaubt den Empfang von Push-Benachrichtigungen.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"IP address" = "IP-Adresse";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Irreversible message deletion" = "Unwiederbringliches löschen einer Nachricht";
|
"Irreversible message deletion" = "Unwiederbringliches löschen einer Nachricht";
|
||||||
|
|
||||||
@@ -2873,6 +2944,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Messages sent" = "Gesendete Nachrichten";
|
"Messages sent" = "Gesendete Nachrichten";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Messages were deleted after you selected them." = "Die Nachrichten wurden gelöscht, nachdem Sie sie ausgewählt hatten.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* 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." = "Nachrichten, Dateien und Anrufe sind durch **Ende-zu-Ende-Verschlüsselung** mit Perfect Forward Secrecy, Ablehnung und Einbruchs-Wiederherstellung geschützt.";
|
"Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." = "Nachrichten, Dateien und Anrufe sind durch **Ende-zu-Ende-Verschlüsselung** mit Perfect Forward Secrecy, Ablehnung und Einbruchs-Wiederherstellung geschützt.";
|
||||||
|
|
||||||
@@ -3026,6 +3100,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"New passphrase…" = "Neues Passwort…";
|
"New passphrase…" = "Neues Passwort…";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"New SOCKS credentials will be used every time you start the app." = "Jedes Mal wenn Sie die App starten, werden neue SOCKS-Anmeldeinformationen genutzt";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"New SOCKS credentials will be used for each server." = "Für jeden Server werden neue SOCKS-Anmeldeinformationen genutzt";
|
||||||
|
|
||||||
/* pref value */
|
/* pref value */
|
||||||
"no" = "Nein";
|
"no" = "Nein";
|
||||||
|
|
||||||
@@ -3068,6 +3148,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"No network connection" = "Keine Netzwerkverbindung";
|
"No network connection" = "Keine Netzwerkverbindung";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"No permission to record speech" = "Keine Genehmigung für Sprach-Aufnahmen";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"No permission to record video" = "Keine Genehmigung für Video-Aufnahmen";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"No permission to record voice message" = "Keine Berechtigung für das Aufnehmen von Sprachnachrichten";
|
"No permission to record voice message" = "Keine Berechtigung für das Aufnehmen von Sprachnachrichten";
|
||||||
|
|
||||||
@@ -3083,6 +3169,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Nothing selected" = "Nichts ausgewählt";
|
"Nothing selected" = "Nichts ausgewählt";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Nothing to forward!" = "Es gibt nichts zum Weiterleiten!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Notifications" = "Benachrichtigungen";
|
"Notifications" = "Benachrichtigungen";
|
||||||
|
|
||||||
@@ -3224,7 +3313,7 @@
|
|||||||
"Or show this code" = "Oder diesen QR-Code anzeigen";
|
"Or show this code" = "Oder diesen QR-Code anzeigen";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"other" = "andere";
|
"other" = "Andere";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Other" = "Andere";
|
"Other" = "Andere";
|
||||||
@@ -3235,6 +3324,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"other errors" = "Andere Fehler";
|
"other errors" = "Andere Fehler";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Other file errors:\n%@" = "Andere(r) Datei-Fehler:\n%@";
|
||||||
|
|
||||||
/* member role */
|
/* member role */
|
||||||
"owner" = "Eigentümer";
|
"owner" = "Eigentümer";
|
||||||
|
|
||||||
@@ -3256,6 +3348,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Passcode set!" = "Zugangscode eingestellt!";
|
"Passcode set!" = "Zugangscode eingestellt!";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Password" = "Passwort";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Password to show" = "Passwort anzeigen";
|
"Password to show" = "Passwort anzeigen";
|
||||||
|
|
||||||
@@ -3352,6 +3447,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Polish interface" = "Polnische Bedienoberfläche";
|
"Polish interface" = "Polnische Bedienoberfläche";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Port" = "Port";
|
||||||
|
|
||||||
/* server test error */
|
/* server test error */
|
||||||
"Possibly, certificate fingerprint in server address is incorrect" = "Der Fingerabdruck des Zertifikats in der Serveradresse ist wahrscheinlich ungültig";
|
"Possibly, certificate fingerprint in server address is incorrect" = "Der Fingerabdruck des Zertifikats in der Serveradresse ist wahrscheinlich ungültig";
|
||||||
|
|
||||||
@@ -3463,6 +3561,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Proxied servers" = "Proxy-Server";
|
"Proxied servers" = "Proxy-Server";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Proxy requires password" = "Der Proxy benötigt ein Passwort";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Push notifications" = "Push-Benachrichtigungen";
|
"Push notifications" = "Push-Benachrichtigungen";
|
||||||
|
|
||||||
@@ -3804,6 +3905,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Saved WebRTC ICE servers will be removed" = "Gespeicherte WebRTC ICE-Server werden entfernt";
|
"Saved WebRTC ICE servers will be removed" = "Gespeicherte WebRTC ICE-Server werden entfernt";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Saving %lld messages" = "Es wird/werden %lld Nachricht(en) gesichert";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Scale" = "Skalieren";
|
"Scale" = "Skalieren";
|
||||||
|
|
||||||
@@ -4002,6 +4106,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Sent via proxy" = "Über einen Proxy gesendet";
|
"Sent via proxy" = "Über einen Proxy gesendet";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Server" = "Server";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Server address" = "Server-Adresse";
|
"Server address" = "Server-Adresse";
|
||||||
|
|
||||||
@@ -4191,6 +4298,9 @@
|
|||||||
/* simplex link type */
|
/* simplex link type */
|
||||||
"SimpleX one-time invitation" = "SimpleX-Einmal-Einladung";
|
"SimpleX one-time invitation" = "SimpleX-Einmal-Einladung";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"SimpleX protocols reviewed by Trail of Bits." = "Die SimpleX-Protokolle wurden von Trail of Bits überprüft.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Simplified incognito mode" = "Vereinfachter Inkognito-Modus";
|
"Simplified incognito mode" = "Vereinfachter Inkognito-Modus";
|
||||||
|
|
||||||
@@ -4209,6 +4319,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"SMP server" = "SMP-Server";
|
"SMP server" = "SMP-Server";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"SOCKS proxy" = "SOCKS-Proxy";
|
||||||
|
|
||||||
/* blur media */
|
/* blur media */
|
||||||
"Soft" = "Weich";
|
"Soft" = "Weich";
|
||||||
|
|
||||||
@@ -4308,6 +4421,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Support SimpleX Chat" = "Unterstützung von SimpleX Chat";
|
"Support SimpleX Chat" = "Unterstützung von SimpleX Chat";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Switch audio and video during the call." = "Während des Anrufs zwischen Audio und Video wechseln";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Switch chat profile for 1-time invitations." = "Das Chat-Profil für Einmal-Einladungen wechseln";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"System" = "System";
|
"System" = "System";
|
||||||
|
|
||||||
@@ -4315,7 +4434,7 @@
|
|||||||
"System authentication" = "System-Authentifizierung";
|
"System authentication" = "System-Authentifizierung";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Tail" = "Sprechblase";
|
"Tail" = "Sprechblasen-Format";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Take picture" = "Machen Sie ein Foto";
|
"Take picture" = "Machen Sie ein Foto";
|
||||||
@@ -4527,6 +4646,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"To protect your IP address, private routing uses your SMP servers to deliver messages." = "Zum Schutz Ihrer IP-Adresse, wird für die Nachrichten-Auslieferung privates Routing über Ihre konfigurierten SMP-Server genutzt.";
|
"To protect your IP address, private routing uses your SMP servers to deliver messages." = "Zum Schutz Ihrer IP-Adresse, wird für die Nachrichten-Auslieferung privates Routing über Ihre konfigurierten SMP-Server genutzt.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"To record speech please grant permission to use Microphone." = "Bitte erteilen Sie für Sprach-Aufnahmen die Genehmigung das Mikrofon zu nutzen.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"To record video please grant permission to use Camera." = "Bitte erteilen Sie für Video-Aufnahmen die Genehmigung die Kamera zu nutzen.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"To record voice message please grant permission to use Microphone." = "Bitte erlauben Sie die Nutzung des Mikrofons, um Sprachnachrichten aufnehmen zu können.";
|
"To record voice message please grant permission to use Microphone." = "Bitte erlauben Sie die Nutzung des Mikrofons, um Sprachnachrichten aufnehmen zu können.";
|
||||||
|
|
||||||
@@ -4743,6 +4868,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Use SimpleX Chat servers?" = "Verwenden Sie SimpleX-Chat-Server?";
|
"Use SimpleX Chat servers?" = "Verwenden Sie SimpleX-Chat-Server?";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Use SOCKS proxy" = "SOCKS-Proxy nutzen";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Use the app while in the call." = "Die App kann während eines Anrufs genutzt werden.";
|
"Use the app while in the call." = "Die App kann während eines Anrufs genutzt werden.";
|
||||||
|
|
||||||
@@ -4750,10 +4878,10 @@
|
|||||||
"Use the app with one hand." = "Die App mit einer Hand bedienen.";
|
"Use the app with one hand." = "Die App mit einer Hand bedienen.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"User profile" = "Benutzerprofil";
|
"User selection" = "Benutzer-Auswahl";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"User selection" = "Benutzer-Auswahl";
|
"Username" = "Benutzername";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Using SimpleX Chat servers." = "Verwendung von SimpleX-Chat-Servern.";
|
"Using SimpleX Chat servers." = "Verwendung von SimpleX-Chat-Servern.";
|
||||||
@@ -4956,9 +5084,6 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"you" = "Profil";
|
"you" = "Profil";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"You" = "Profil";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"You **must not** use the same database on two devices." = "Sie dürfen die selbe Datenbank **nicht** auf zwei Geräten nutzen.";
|
"You **must not** use the same database on two devices." = "Sie dürfen die selbe Datenbank **nicht** auf zwei Geräten nutzen.";
|
||||||
|
|
||||||
@@ -5211,6 +5336,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your contacts will remain connected." = "Ihre Kontakte bleiben weiterhin verbunden.";
|
"Your contacts will remain connected." = "Ihre Kontakte bleiben weiterhin verbunden.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Your credentials may be sent unencrypted." = "Ihre Anmeldeinformationen können unverschlüsselt versendet werden.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your current chat database will be DELETED and REPLACED with the imported one." = "Ihre aktuelle Chat-Datenbank wird GELÖSCHT und durch die Importierte ERSETZT.";
|
"Your current chat database will be DELETED and REPLACED with the imported one." = "Ihre aktuelle Chat-Datenbank wird GELÖSCHT und durch die Importierte ERSETZT.";
|
||||||
|
|
||||||
|
|||||||
@@ -160,6 +160,9 @@
|
|||||||
/* notification title */
|
/* notification title */
|
||||||
"%@ wants to connect!" = "¡ %@ quiere contactar!";
|
"%@ wants to connect!" = "¡ %@ quiere contactar!";
|
||||||
|
|
||||||
|
/* format for date separator in chat */
|
||||||
|
"%@, %@" = "%1$@, %2$@";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"%@, %@ and %lld members" = "%@, %@ y %lld miembro(s) más";
|
"%@, %@ and %lld members" = "%@, %@ y %lld miembro(s) más";
|
||||||
|
|
||||||
@@ -172,9 +175,24 @@
|
|||||||
/* time interval */
|
/* time interval */
|
||||||
"%d days" = "%d días";
|
"%d days" = "%d días";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) are still being downloaded." = "%d archivo(s) se está(n) descargando todavía.";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) failed to download." = "La descarga ha fallado para %d archivo(s).";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) were deleted." = "%d archivo(s) ha(n) sido eliminado(s).";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) were not downloaded." = "%d archivo(s) no se ha(n) descargado.";
|
||||||
|
|
||||||
/* time interval */
|
/* time interval */
|
||||||
"%d hours" = "%d horas";
|
"%d hours" = "%d horas";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"%d messages not forwarded" = "%d mensajes no enviados";
|
||||||
|
|
||||||
/* time interval */
|
/* time interval */
|
||||||
"%d min" = "%d minutos";
|
"%d min" = "%d minutos";
|
||||||
|
|
||||||
@@ -305,7 +323,7 @@
|
|||||||
"A new contact" = "Contacto nuevo";
|
"A new contact" = "Contacto nuevo";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"A new random profile will be shared." = "Se compartirá un perfil nuevo aleatorio.";
|
"A new random profile will be shared." = "Compartirás un perfil nuevo aleatorio.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"A separate TCP connection will be used **for each chat profile you have in the app**." = "Se usará una conexión TCP independiente **por cada perfil que tengas en la aplicación**.";
|
"A separate TCP connection will be used **for each chat profile you have in the app**." = "Se usará una conexión TCP independiente **por cada perfil que tengas en la aplicación**.";
|
||||||
@@ -454,7 +472,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"All new messages from %@ will be hidden!" = "¡Los mensajes nuevos de %@ estarán ocultos!";
|
"All new messages from %@ will be hidden!" = "¡Los mensajes nuevos de %@ estarán ocultos!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* profile dropdown */
|
||||||
"All profiles" = "Todos los perfiles";
|
"All profiles" = "Todos los perfiles";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -577,6 +595,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"App passcode is replaced with self-destruct passcode." = "El código de acceso será reemplazado por código de autodestrucción.";
|
"App passcode is replaced with self-destruct passcode." = "El código de acceso será reemplazado por código de autodestrucción.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"App session" = "Sesión de aplicación";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"App version" = "Versión de la aplicación";
|
"App version" = "Versión de la aplicación";
|
||||||
|
|
||||||
@@ -649,6 +670,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Auto-accept images" = "Aceptar imágenes automáticamente";
|
"Auto-accept images" = "Aceptar imágenes automáticamente";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Auto-accept settings" = "Auto aceptar configuración";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Back" = "Volver";
|
"Back" = "Volver";
|
||||||
|
|
||||||
@@ -670,15 +694,30 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Bad message ID" = "ID de mensaje incorrecto";
|
"Bad message ID" = "ID de mensaje incorrecto";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better calls" = "Llamadas mejoradas";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Better groups" = "Grupos mejorados";
|
"Better groups" = "Grupos mejorados";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better message dates." = "Sistema de fechas mejorado.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Better messages" = "Mensajes mejorados";
|
"Better messages" = "Mensajes mejorados";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Better networking" = "Uso de red mejorado";
|
"Better networking" = "Uso de red mejorado";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better notifications" = "Notificaciones mejoradas";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better security ✅" = "Seguridad mejorada ✅";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better user experience" = "Experiencia de usuario mejorada";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Black" = "Negro";
|
"Black" = "Negro";
|
||||||
|
|
||||||
@@ -890,6 +929,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chat preferences" = "Preferencias de Chat";
|
"Chat preferences" = "Preferencias de Chat";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Chat preferences were changed." = "Las preferencias del chat han sido modificadas.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Chat profile" = "Perfil de usuario";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chat theme" = "Tema de chat";
|
"Chat theme" = "Tema de chat";
|
||||||
|
|
||||||
@@ -987,7 +1032,7 @@
|
|||||||
"Confirm password" = "Confirmar contraseña";
|
"Confirm password" = "Confirmar contraseña";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Confirm that you remember database passphrase to migrate it." = "Para migrar confirma que recuerdas la frase de contraseña de la base de datos.";
|
"Confirm that you remember database passphrase to migrate it." = "Para migrar la base de datos confirma que recuerdas la frase de contraseña.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Confirm upload" = "Confirmar subida";
|
"Confirm upload" = "Confirmar subida";
|
||||||
@@ -1178,6 +1223,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Core version: v%@" = "Versión Core: v%@";
|
"Core version: v%@" = "Versión Core: v%@";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Corner" = "Esquina";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Correct name to %@?" = "¿Corregir el nombre a %@?";
|
"Correct name to %@?" = "¿Corregir el nombre a %@?";
|
||||||
|
|
||||||
@@ -1259,6 +1307,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Custom time" = "Tiempo personalizado";
|
"Custom time" = "Tiempo personalizado";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Customizable message shape." = "Forma personalizable de los mensajes.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Customize theme" = "Personalizar tema";
|
"Customize theme" = "Personalizar tema";
|
||||||
|
|
||||||
@@ -1305,7 +1356,7 @@
|
|||||||
"Database passphrase & export" = "Base de datos y contraseña";
|
"Database passphrase & export" = "Base de datos y contraseña";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Database passphrase is different from saved in the keychain." = "La contraseña es distinta a la almacenada en Keychain.";
|
"Database passphrase is different from saved in the keychain." = "La contraseña es diferente a la almacenada en Keychain.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Database passphrase is required to open chat." = "Para abrir la aplicación se requiere la contraseña de la base de datos.";
|
"Database passphrase is required to open chat." = "Para abrir la aplicación se requiere la contraseña de la base de datos.";
|
||||||
@@ -1449,6 +1500,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Delete old database?" = "¿Eliminar base de datos antigua?";
|
"Delete old database?" = "¿Eliminar base de datos antigua?";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Delete or moderate up to 200 messages." = "Borra o modera hasta 200 mensajes a la vez.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Delete pending connection?" = "¿Eliminar conexión pendiente?";
|
"Delete pending connection?" = "¿Eliminar conexión pendiente?";
|
||||||
|
|
||||||
@@ -1594,7 +1648,7 @@
|
|||||||
"Disconnect" = "Desconectar";
|
"Disconnect" = "Desconectar";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Disconnect desktop?" = "¿Desconectar ordenador?";
|
"Disconnect desktop?" = "¿Desconectar del ordenador?";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Discover and join groups" = "Descubre y únete a grupos";
|
"Discover and join groups" = "Descubre y únete a grupos";
|
||||||
@@ -1611,6 +1665,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Do NOT send messages directly, even if your or destination server does not support private routing." = "NO enviar mensajes directamente incluso si tu servidor o el de destino no soportan enrutamiento privado.";
|
"Do NOT send messages directly, even if your or destination server does not support private routing." = "NO enviar mensajes directamente incluso si tu servidor o el de destino no soportan enrutamiento privado.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Do not use credentials with proxy." = "No uses credenciales con proxy.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Do NOT use private routing." = "NO usar enrutamiento privado.";
|
"Do NOT use private routing." = "NO usar enrutamiento privado.";
|
||||||
|
|
||||||
@@ -1624,7 +1681,7 @@
|
|||||||
"Don't enable" = "No activar";
|
"Don't enable" = "No activar";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Don't show again" = "No mostrar de nuevo";
|
"Don't show again" = "No volver a mostrar";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Downgrade and open chat" = "Degradar y abrir Chat";
|
"Downgrade and open chat" = "Degradar y abrir Chat";
|
||||||
@@ -1642,6 +1699,9 @@
|
|||||||
/* server test step */
|
/* server test step */
|
||||||
"Download file" = "Descargar archivo";
|
"Download file" = "Descargar archivo";
|
||||||
|
|
||||||
|
/* alert action */
|
||||||
|
"Download files" = "Descargar archivos";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Downloaded" = "Descargado";
|
"Downloaded" = "Descargado";
|
||||||
|
|
||||||
@@ -1858,12 +1918,18 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error changing address" = "Error al cambiar servidor";
|
"Error changing address" = "Error al cambiar servidor";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Error changing connection profile" = "Error al cambiar el perfil de conexión";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error changing role" = "Error al cambiar rol";
|
"Error changing role" = "Error al cambiar rol";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error changing setting" = "Error cambiando configuración";
|
"Error changing setting" = "Error cambiando configuración";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Error changing to incognito!" = "¡Error al cambiar a incógnito!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error connecting to forwarding server %@. Please try later." = "Error al conectar con el servidor de reenvío %@. Por favor, inténtalo más tarde.";
|
"Error connecting to forwarding server %@. Please try later." = "Error al conectar con el servidor de reenvío %@. Por favor, inténtalo más tarde.";
|
||||||
|
|
||||||
@@ -1936,6 +2002,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error loading %@ servers" = "Error al cargar servidores %@";
|
"Error loading %@ servers" = "Error al cargar servidores %@";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Error migrating settings" = "Error al migrar la configuración";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error opening chat" = "Error al abrir chat";
|
"Error opening chat" = "Error al abrir chat";
|
||||||
|
|
||||||
@@ -1997,6 +2066,9 @@
|
|||||||
"Error stopping chat" = "Error al parar SimpleX";
|
"Error stopping chat" = "Error al parar SimpleX";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
|
"Error switching profile" = "Error al cambiar perfil";
|
||||||
|
|
||||||
|
/* alertTitle */
|
||||||
"Error switching profile!" = "¡Error al cambiar perfil!";
|
"Error switching profile!" = "¡Error al cambiar perfil!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -2023,8 +2095,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error: " = "Error: ";
|
"Error: " = "Error: ";
|
||||||
|
|
||||||
/* file error text
|
/* alert message */
|
||||||
snd error text */
|
|
||||||
"Error: %@" = "Error: %@";
|
"Error: %@" = "Error: %@";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -2084,6 +2155,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"File error" = "Error de archivo";
|
"File error" = "Error de archivo";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"File errors:\n%@" = "Error(es) de archivo\n%@";
|
||||||
|
|
||||||
/* file error text */
|
/* file error text */
|
||||||
"File not found - most likely file was deleted or cancelled." = "Archivo no encontrado, probablemente haya sido borrado o cancelado.";
|
"File not found - most likely file was deleted or cancelled." = "Archivo no encontrado, probablemente haya sido borrado o cancelado.";
|
||||||
|
|
||||||
@@ -2165,9 +2239,21 @@
|
|||||||
/* chat item action */
|
/* chat item action */
|
||||||
"Forward" = "Reenviar";
|
"Forward" = "Reenviar";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Forward %d message(s)?" = "¿Reenviar %d mensaje(s)?";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Forward and save messages" = "Reenviar y guardar mensajes";
|
"Forward and save messages" = "Reenviar y guardar mensajes";
|
||||||
|
|
||||||
|
/* alert action */
|
||||||
|
"Forward messages" = "Reenviar mensajes";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Forward messages without files?" = "¿Reenviar mensajes sin los archivos?";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Forward up to 20 messages at once." = "Desplazamiento de hasta 20 mensajes.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"forwarded" = "reenviado";
|
"forwarded" = "reenviado";
|
||||||
|
|
||||||
@@ -2177,6 +2263,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Forwarded from" = "Reenviado por";
|
"Forwarded from" = "Reenviado por";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Forwarding %lld messages" = "Reenviando %lld mensajes";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Forwarding server %@ failed to connect to destination server %@. Please try later." = "El servidor de reenvío %@ no ha podido conectarse al servidor de destino %@. Por favor, intentalo más tarde.";
|
"Forwarding server %@ failed to connect to destination server %@. Please try later." = "El servidor de reenvío %@ no ha podido conectarse al servidor de destino %@. Por favor, intentalo más tarde.";
|
||||||
|
|
||||||
@@ -2205,10 +2294,10 @@
|
|||||||
"Full name (optional)" = "Nombre completo (opcional)";
|
"Full name (optional)" = "Nombre completo (opcional)";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Fully decentralized – visible only to members." = "Completamente descentralizado y sólo visible para los miembros.";
|
"Fully decentralized – visible only to members." = "Totalmente descentralizado. Visible sólo para los miembros.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Fully re-implemented - work in background!" = "Completamente reimplementado: ¡funciona en segundo plano!";
|
"Fully re-implemented - work in background!" = "Totalmente revisado. ¡Funciona en segundo plano!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Further reduced battery usage" = "Reducción consumo de batería";
|
"Further reduced battery usage" = "Reducción consumo de batería";
|
||||||
@@ -2405,6 +2494,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Importing archive" = "Importando archivo";
|
"Importing archive" = "Importando archivo";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Improved delivery, reduced traffic usage.\nMore improvements are coming soon!" = "Reducción del tráfico y entrega mejorada.\n¡Pronto habrá nuevas mejoras!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Improved message delivery" = "Entrega de mensajes mejorada";
|
"Improved message delivery" = "Entrega de mensajes mejorada";
|
||||||
|
|
||||||
@@ -2564,6 +2656,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "iOS Keychain se usará para almacenar la contraseña de forma segura después de reiniciar la aplicación o cambiar la contraseña. Esto permitirá recibir notificaciones automáticas.";
|
"iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "iOS Keychain se usará para almacenar la contraseña de forma segura después de reiniciar la aplicación o cambiar la contraseña. Esto permitirá recibir notificaciones automáticas.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"IP address" = "Dirección IP";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Irreversible message deletion" = "Eliminación irreversible del mensaje";
|
"Irreversible message deletion" = "Eliminación irreversible del mensaje";
|
||||||
|
|
||||||
@@ -2697,7 +2792,7 @@
|
|||||||
"Local name" = "Nombre local";
|
"Local name" = "Nombre local";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Local profile data only" = "Sólo datos del perfil local";
|
"Local profile data only" = "Eliminar sólo el perfil";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Lock after" = "Bloquear en";
|
"Lock after" = "Bloquear en";
|
||||||
@@ -2816,6 +2911,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Message servers" = "Servidores de mensajes";
|
"Message servers" = "Servidores de mensajes";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Message shape" = "Forma del mensaje";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Message source remains private." = "El autor del mensaje se mantiene privado.";
|
"Message source remains private." = "El autor del mensaje se mantiene privado.";
|
||||||
|
|
||||||
@@ -2846,6 +2944,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Messages sent" = "Mensajes enviados";
|
"Messages sent" = "Mensajes enviados";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Messages were deleted after you selected them." = "Los mensajes han sido borrados después de seleccionarlos.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* 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." = "Los mensajes, archivos y llamadas están protegidos mediante **cifrado de extremo a extremo** con secreto perfecto hacía adelante, repudio y recuperación tras ataque.";
|
"Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." = "Los mensajes, archivos y llamadas están protegidos mediante **cifrado de extremo a extremo** con secreto perfecto hacía adelante, repudio y recuperación tras ataque.";
|
||||||
|
|
||||||
@@ -2999,6 +3100,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"New passphrase…" = "Contraseña nueva…";
|
"New passphrase…" = "Contraseña nueva…";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"New SOCKS credentials will be used every time you start the app." = "Se usarán credenciales SOCKS nuevas cada vez que inicies la aplicación.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"New SOCKS credentials will be used for each server." = "Se usarán credenciales SOCKS nuevas por cada servidor.";
|
||||||
|
|
||||||
/* pref value */
|
/* pref value */
|
||||||
"no" = "no";
|
"no" = "no";
|
||||||
|
|
||||||
@@ -3041,6 +3148,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"No network connection" = "Sin conexión de red";
|
"No network connection" = "Sin conexión de red";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"No permission to record speech" = "Sin permiso para grabación de voz";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"No permission to record video" = "Sin permiso para grabación de vídeo";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"No permission to record voice message" = "Sin permiso para grabar mensajes de voz";
|
"No permission to record voice message" = "Sin permiso para grabar mensajes de voz";
|
||||||
|
|
||||||
@@ -3056,6 +3169,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Nothing selected" = "Nada seleccionado";
|
"Nothing selected" = "Nada seleccionado";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Nothing to forward!" = "¡Nada para reenviar!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Notifications" = "Notificaciones";
|
"Notifications" = "Notificaciones";
|
||||||
|
|
||||||
@@ -3208,6 +3324,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"other errors" = "otros errores";
|
"other errors" = "otros errores";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Other file errors:\n%@" = "Otro(s) error(es) de archivo.\n%@";
|
||||||
|
|
||||||
/* member role */
|
/* member role */
|
||||||
"owner" = "propietario";
|
"owner" = "propietario";
|
||||||
|
|
||||||
@@ -3229,6 +3348,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Passcode set!" = "¡Código de acceso guardado!";
|
"Passcode set!" = "¡Código de acceso guardado!";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Password" = "Contraseña";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Password to show" = "Contraseña para hacerlo visible";
|
"Password to show" = "Contraseña para hacerlo visible";
|
||||||
|
|
||||||
@@ -3325,8 +3447,11 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Polish interface" = "Interfaz en polaco";
|
"Polish interface" = "Interfaz en polaco";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Port" = "Puerto";
|
||||||
|
|
||||||
/* server test error */
|
/* server test error */
|
||||||
"Possibly, certificate fingerprint in server address is incorrect" = "Posiblemente la huella digital del certificado en la dirección del servidor es incorrecta";
|
"Possibly, certificate fingerprint in server address is incorrect" = "Posiblemente la huella del certificado en la dirección del servidor es incorrecta";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Preserve the last message draft, with attachments." = "Conserva el último borrador del mensaje con los datos adjuntos.";
|
"Preserve the last message draft, with attachments." = "Conserva el último borrador del mensaje con los datos adjuntos.";
|
||||||
@@ -3368,7 +3493,7 @@
|
|||||||
"Private routing error" = "Error de enrutamiento privado";
|
"Private routing error" = "Error de enrutamiento privado";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Profile and server connections" = "Datos del perfil y conexiones";
|
"Profile and server connections" = "Eliminar perfil y conexiones";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Profile image" = "Imagen del perfil";
|
"Profile image" = "Imagen del perfil";
|
||||||
@@ -3436,6 +3561,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Proxied servers" = "Servidores con proxy";
|
"Proxied servers" = "Servidores con proxy";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Proxy requires password" = "El proxy requiere contraseña";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Push notifications" = "Notificaciones automáticas";
|
"Push notifications" = "Notificaciones automáticas";
|
||||||
|
|
||||||
@@ -3581,6 +3709,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Remove" = "Eliminar";
|
"Remove" = "Eliminar";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Remove archive?" = "¿Eliminar archivo?";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Remove image" = "Eliminar imagen";
|
"Remove image" = "Eliminar imagen";
|
||||||
|
|
||||||
@@ -3603,7 +3734,7 @@
|
|||||||
"removed contact address" = "dirección de contacto eliminada";
|
"removed contact address" = "dirección de contacto eliminada";
|
||||||
|
|
||||||
/* profile update event chat item */
|
/* profile update event chat item */
|
||||||
"removed profile picture" = "imagen de perfil eliminada";
|
"removed profile picture" = "ha eliminado la imagen del perfil";
|
||||||
|
|
||||||
/* rcv group event chat item */
|
/* rcv group event chat item */
|
||||||
"removed you" = "te ha expulsado";
|
"removed you" = "te ha expulsado";
|
||||||
@@ -3753,6 +3884,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Save welcome message?" = "¿Guardar mensaje de bienvenida?";
|
"Save welcome message?" = "¿Guardar mensaje de bienvenida?";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Save your profile?" = "¿Guardar tu perfil?";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"saved" = "guardado";
|
"saved" = "guardado";
|
||||||
|
|
||||||
@@ -3771,6 +3905,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Saved WebRTC ICE servers will be removed" = "Los servidores WebRTC ICE guardados serán eliminados";
|
"Saved WebRTC ICE servers will be removed" = "Los servidores WebRTC ICE guardados serán eliminados";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Saving %lld messages" = "Guardando %lld mensajes";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Scale" = "Escala";
|
"Scale" = "Escala";
|
||||||
|
|
||||||
@@ -3834,6 +3971,9 @@
|
|||||||
/* chat item action */
|
/* chat item action */
|
||||||
"Select" = "Seleccionar";
|
"Select" = "Seleccionar";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Select chat profile" = "Selecciona perfil de chat";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Selected %lld" = "Seleccionados %lld";
|
"Selected %lld" = "Seleccionados %lld";
|
||||||
|
|
||||||
@@ -3865,7 +4005,7 @@
|
|||||||
"send direct message" = "Enviar mensaje directo";
|
"send direct message" = "Enviar mensaje directo";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Send direct message to connect" = "Envia un mensaje para conectar";
|
"Send direct message to connect" = "Envía un mensaje para conectar";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Send disappearing message" = "Enviar mensaje temporal";
|
"Send disappearing message" = "Enviar mensaje temporal";
|
||||||
@@ -3966,6 +4106,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Sent via proxy" = "Mediante proxy";
|
"Sent via proxy" = "Mediante proxy";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Server" = "Servidor";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Server address" = "Dirección del servidor";
|
"Server address" = "Dirección del servidor";
|
||||||
|
|
||||||
@@ -3985,7 +4128,7 @@
|
|||||||
"Server requires authorization to upload, check password" = "El servidor requiere autorización para subir, comprueba la contraseña";
|
"Server requires authorization to upload, check password" = "El servidor requiere autorización para subir, comprueba la contraseña";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Server test failed!" = "¡Error en prueba del servidor!";
|
"Server test failed!" = "¡Prueba no superada!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Server type" = "Tipo de servidor";
|
"Server type" = "Tipo de servidor";
|
||||||
@@ -4027,7 +4170,7 @@
|
|||||||
"set new contact address" = "nueva dirección de contacto";
|
"set new contact address" = "nueva dirección de contacto";
|
||||||
|
|
||||||
/* profile update event chat item */
|
/* profile update event chat item */
|
||||||
"set new profile picture" = "nueva imagen de perfil";
|
"set new profile picture" = "tiene nueva imagen del perfil";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Set passcode" = "Código autodestrucción";
|
"Set passcode" = "Código autodestrucción";
|
||||||
@@ -4047,6 +4190,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Settings" = "Configuración";
|
"Settings" = "Configuración";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Settings were changed." = "La configuración ha sido modificada.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Shape profile images" = "Dar forma a las imágenes de perfil";
|
"Shape profile images" = "Dar forma a las imágenes de perfil";
|
||||||
|
|
||||||
@@ -4068,6 +4214,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Share link" = "Compartir enlace";
|
"Share link" = "Compartir enlace";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Share profile" = "Comparte perfil";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Share this 1-time invite link" = "Comparte este enlace de un solo uso";
|
"Share this 1-time invite link" = "Comparte este enlace de un solo uso";
|
||||||
|
|
||||||
@@ -4149,6 +4298,9 @@
|
|||||||
/* simplex link type */
|
/* simplex link type */
|
||||||
"SimpleX one-time invitation" = "Invitación SimpleX de un uso";
|
"SimpleX one-time invitation" = "Invitación SimpleX de un uso";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"SimpleX protocols reviewed by Trail of Bits." = "Protocolos de SimpleX auditados por Trail of Bits.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Simplified incognito mode" = "Modo incógnito simplificado";
|
"Simplified incognito mode" = "Modo incógnito simplificado";
|
||||||
|
|
||||||
@@ -4167,9 +4319,15 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"SMP server" = "Servidor SMP";
|
"SMP server" = "Servidor SMP";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"SOCKS proxy" = "Proxy SOCKS";
|
||||||
|
|
||||||
/* blur media */
|
/* blur media */
|
||||||
"Soft" = "Suave";
|
"Soft" = "Suave";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Some app settings were not migrated." = "Algunas configuraciones de la app no han sido migradas.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Some file(s) were not exported:" = "Algunos archivos no han sido exportados:";
|
"Some file(s) were not exported:" = "Algunos archivos no han sido exportados:";
|
||||||
|
|
||||||
@@ -4263,12 +4421,21 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Support SimpleX Chat" = "Soporte SimpleX Chat";
|
"Support SimpleX Chat" = "Soporte SimpleX Chat";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Switch audio and video during the call." = "Intercambia audio y video durante la llamada.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Switch chat profile for 1-time invitations." = "Cambia el perfil de chat para invitaciones de un solo uso.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"System" = "Sistema";
|
"System" = "Sistema";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"System authentication" = "Autenticación del sistema";
|
"System authentication" = "Autenticación del sistema";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Tail" = "Cola";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Take picture" = "Tomar foto";
|
"Take picture" = "Tomar foto";
|
||||||
|
|
||||||
@@ -4312,7 +4479,7 @@
|
|||||||
"Temporary file error" = "Error en archivo temporal";
|
"Temporary file error" = "Error en archivo temporal";
|
||||||
|
|
||||||
/* server test failure */
|
/* server test failure */
|
||||||
"Test failed at step %@." = "La prueba ha fallado en el paso %@.";
|
"Test failed at step %@." = "Prueba no superada en el paso %@.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Test server" = "Probar servidor";
|
"Test server" = "Probar servidor";
|
||||||
@@ -4321,7 +4488,7 @@
|
|||||||
"Test servers" = "Probar servidores";
|
"Test servers" = "Probar servidores";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Tests failed!" = "¡Pruebas fallidas!";
|
"Tests failed!" = "¡Pruebas no superadas!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Thank you for installing SimpleX Chat!" = "¡Gracias por instalar SimpleX Chat!";
|
"Thank you for installing SimpleX Chat!" = "¡Gracias por instalar SimpleX Chat!";
|
||||||
@@ -4398,6 +4565,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"The text you pasted is not a SimpleX link." = "El texto pegado no es un enlace SimpleX.";
|
"The text you pasted is not a SimpleX link." = "El texto pegado no es un enlace SimpleX.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"The uploaded database archive will be permanently removed from the servers." = "El archivo de bases de datos subido será eliminado permanentemente de los servidores.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Themes" = "Temas";
|
"Themes" = "Temas";
|
||||||
|
|
||||||
@@ -4476,6 +4646,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"To protect your IP address, private routing uses your SMP servers to deliver messages." = "Para proteger tu dirección IP, el enrutamiento privado usa tu lista de servidores SMP para enviar mensajes.";
|
"To protect your IP address, private routing uses your SMP servers to deliver messages." = "Para proteger tu dirección IP, el enrutamiento privado usa tu lista de servidores SMP para enviar mensajes.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"To record speech please grant permission to use Microphone." = "Para grabación de voz, por favor concede el permiso para usar el micrófono.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"To record video please grant permission to use Camera." = "Para grabación de vídeo, por favor concede el permiso para usar la cámara.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"To record voice message please grant permission to use Microphone." = "Para grabar el mensaje de voz concede permiso para usar el micrófono.";
|
"To record voice message please grant permission to use Microphone." = "Para grabar el mensaje de voz concede permiso para usar el micrófono.";
|
||||||
|
|
||||||
@@ -4692,6 +4868,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Use SimpleX Chat servers?" = "¿Usar servidores SimpleX Chat?";
|
"Use SimpleX Chat servers?" = "¿Usar servidores SimpleX Chat?";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Use SOCKS proxy" = "Usar proxy SOCKS";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Use the app while in the call." = "Usar la aplicación durante la llamada.";
|
"Use the app while in the call." = "Usar la aplicación durante la llamada.";
|
||||||
|
|
||||||
@@ -4699,10 +4878,10 @@
|
|||||||
"Use the app with one hand." = "Usa la aplicación con una sola mano.";
|
"Use the app with one hand." = "Usa la aplicación con una sola mano.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"User profile" = "Perfil de usuario";
|
"User selection" = "Selección de usuarios";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"User selection" = "Selección de usuarios";
|
"Username" = "Nombre de usuario";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Using SimpleX Chat servers." = "Usar servidores SimpleX Chat.";
|
"Using SimpleX Chat servers." = "Usar servidores SimpleX Chat.";
|
||||||
@@ -4905,9 +5084,6 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"you" = "tu";
|
"you" = "tu";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"You" = "Tú";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"You **must not** use the same database on two devices." = "**No debes** usar la misma base de datos en dos dispositivos.";
|
"You **must not** use the same database on two devices." = "**No debes** usar la misma base de datos en dos dispositivos.";
|
||||||
|
|
||||||
@@ -5142,9 +5318,15 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your chat database is not encrypted - set passphrase to encrypt it." = "La base de datos no está cifrada - establece una contraseña para cifrarla.";
|
"Your chat database is not encrypted - set passphrase to encrypt it." = "La base de datos no está cifrada - establece una contraseña para cifrarla.";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Your chat preferences" = "Tus preferencias de chat";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your chat profiles" = "Mis perfiles";
|
"Your chat profiles" = "Mis perfiles";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile." = "Tu conexión ha sido trasladada a %@ pero ha ocurrido un error inesperado al redirigirte al perfil.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your contact sent a file that is larger than currently supported maximum size (%@)." = "El contacto ha enviado un archivo mayor al máximo admitido (%@).";
|
"Your contact sent a file that is larger than currently supported maximum size (%@)." = "El contacto ha enviado un archivo mayor al máximo admitido (%@).";
|
||||||
|
|
||||||
@@ -5154,6 +5336,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your contacts will remain connected." = "Tus contactos permanecerán conectados.";
|
"Your contacts will remain connected." = "Tus contactos permanecerán conectados.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Your credentials may be sent unencrypted." = "Tus credenciales podrían ser enviadas sin cifrar.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your current chat database will be DELETED and REPLACED with the imported one." = "La base de datos actual será ELIMINADA y SUSTITUIDA por la importada.";
|
"Your current chat database will be DELETED and REPLACED with the imported one." = "La base de datos actual será ELIMINADA y SUSTITUIDA por la importada.";
|
||||||
|
|
||||||
@@ -5178,6 +5363,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Tu perfil es almacenado en tu dispositivo y solamente se comparte con tus contactos. Los servidores SimpleX no pueden ver tu perfil.";
|
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Tu perfil es almacenado en tu dispositivo y solamente se comparte con tus contactos. Los servidores SimpleX no pueden ver tu perfil.";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Your profile was changed. If you save it, the updated profile will be sent to all your contacts." = "Tu perfil ha sido modificado. Si lo guardas la actualización será enviada a todos tus contactos.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your profile, contacts and delivered messages are stored on your device." = "Tu perfil, contactos y mensajes se almacenan en tu dispositivo.";
|
"Your profile, contacts and delivered messages are stored on your device." = "Tu perfil, contactos y mensajes se almacenan en tu dispositivo.";
|
||||||
|
|
||||||
@@ -5188,7 +5376,7 @@
|
|||||||
"Your server" = "Tu servidor";
|
"Your server" = "Tu servidor";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your server address" = "Dirección de tu servidor";
|
"Your server address" = "Dirección del servidor";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your settings" = "Configuración";
|
"Your settings" = "Configuración";
|
||||||
|
|||||||
@@ -629,6 +629,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chat preferences" = "Chat-asetukset";
|
"Chat preferences" = "Chat-asetukset";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Chat profile" = "Käyttäjäprofiili";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chats" = "Keskustelut";
|
"Chats" = "Keskustelut";
|
||||||
|
|
||||||
@@ -1395,7 +1398,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error stopping chat" = "Virhe keskustelun lopettamisessa";
|
"Error stopping chat" = "Virhe keskustelun lopettamisessa";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* alertTitle */
|
||||||
"Error switching profile!" = "Virhe profiilin vaihdossa!";
|
"Error switching profile!" = "Virhe profiilin vaihdossa!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -1416,8 +1419,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error: " = "Virhe: ";
|
"Error: " = "Virhe: ";
|
||||||
|
|
||||||
/* file error text
|
/* alert message */
|
||||||
snd error text */
|
|
||||||
"Error: %@" = "Virhe: %@";
|
"Error: %@" = "Virhe: %@";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -3188,9 +3190,6 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Use SimpleX Chat servers?" = "Käytä SimpleX Chat palvelimia?";
|
"Use SimpleX Chat servers?" = "Käytä SimpleX Chat palvelimia?";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"User profile" = "Käyttäjäprofiili";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Using SimpleX Chat servers." = "Käyttää SimpleX Chat -palvelimia.";
|
"Using SimpleX Chat servers." = "Käyttää SimpleX Chat -palvelimia.";
|
||||||
|
|
||||||
@@ -3308,9 +3307,6 @@
|
|||||||
/* pref value */
|
/* pref value */
|
||||||
"yes" = "kyllä";
|
"yes" = "kyllä";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"You" = "Sinä";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"You accepted connection" = "Hyväksyit yhteyden";
|
"You accepted connection" = "Hyväksyit yhteyden";
|
||||||
|
|
||||||
|
|||||||
@@ -454,7 +454,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"All new messages from %@ will be hidden!" = "Tous les nouveaux messages de %@ seront cachés !";
|
"All new messages from %@ will be hidden!" = "Tous les nouveaux messages de %@ seront cachés !";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* profile dropdown */
|
||||||
"All profiles" = "Tous les profiles";
|
"All profiles" = "Tous les profiles";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -890,6 +890,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chat preferences" = "Préférences de chat";
|
"Chat preferences" = "Préférences de chat";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Chat profile" = "Profil d'utilisateur";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chat theme" = "Thème de chat";
|
"Chat theme" = "Thème de chat";
|
||||||
|
|
||||||
@@ -1996,7 +1999,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error stopping chat" = "Erreur lors de l'arrêt du chat";
|
"Error stopping chat" = "Erreur lors de l'arrêt du chat";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* alertTitle */
|
||||||
"Error switching profile!" = "Erreur lors du changement de profil !";
|
"Error switching profile!" = "Erreur lors du changement de profil !";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -2023,8 +2026,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error: " = "Erreur : ";
|
"Error: " = "Erreur : ";
|
||||||
|
|
||||||
/* file error text
|
/* alert message */
|
||||||
snd error text */
|
|
||||||
"Error: %@" = "Erreur : %@";
|
"Error: %@" = "Erreur : %@";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -4698,9 +4700,6 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Use the app with one hand." = "Utiliser l'application d'une main.";
|
"Use the app with one hand." = "Utiliser l'application d'une main.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"User profile" = "Profil d'utilisateur";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"User selection" = "Sélection de l'utilisateur";
|
"User selection" = "Sélection de l'utilisateur";
|
||||||
|
|
||||||
@@ -4905,9 +4904,6 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"you" = "vous";
|
"you" = "vous";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"You" = "Vous";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"You **must not** use the same database on two devices." = "Vous **ne devez pas** utiliser la même base de données sur deux appareils.";
|
"You **must not** use the same database on two devices." = "Vous **ne devez pas** utiliser la même base de données sur deux appareils.";
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
|||||||
"CFBundleName" = "SimpleX";
|
"CFBundleName" = "SimpleX";
|
||||||
|
|
||||||
/* Privacy - Camera Usage Description */
|
/* Privacy - Camera Usage Description */
|
||||||
"NSCameraUsageDescription" = "A SimpleX-nek kamera-hozzáférésre van szüksége a QR-kódok beolvasásához, hogy kapcsolódhasson más felhasználókhoz és videohívásokhoz.";
|
"NSCameraUsageDescription" = "A SimpleXnek kamera-hozzáférésre van szüksége a QR-kódok beolvasásához, hogy kapcsolódhasson más felhasználókhoz és videohívásokhoz.";
|
||||||
|
|
||||||
/* Privacy - Face ID Usage Description */
|
/* Privacy - Face ID Usage Description */
|
||||||
"NSFaceIDUsageDescription" = "A SimpleX Face ID-t használ a helyi hitelesítéshez";
|
"NSFaceIDUsageDescription" = "A SimpleX Face ID-t használ a helyi hitelesítéshez";
|
||||||
@@ -11,8 +11,8 @@
|
|||||||
"NSLocalNetworkUsageDescription" = "A SimpleX helyi hálózati hozzáférést használ, hogy lehetővé tegye a felhasználói csevegőprofil használatát számítógépen keresztül ugyanazon a hálózaton.";
|
"NSLocalNetworkUsageDescription" = "A SimpleX helyi hálózati hozzáférést használ, hogy lehetővé tegye a felhasználói csevegőprofil használatát számítógépen keresztül ugyanazon a hálózaton.";
|
||||||
|
|
||||||
/* Privacy - Microphone Usage Description */
|
/* Privacy - Microphone Usage Description */
|
||||||
"NSMicrophoneUsageDescription" = "A SimpleX-nek mikrofon-hozzáférésre van szüksége hang- és videohívásokhoz, valamint hangüzenetek rögzítéséhez.";
|
"NSMicrophoneUsageDescription" = "A SimpleXnek mikrofon-hozzáférésre van szüksége hang- és videohívásokhoz, valamint hangüzenetek rögzítéséhez.";
|
||||||
|
|
||||||
/* Privacy - Photo Library Additions Usage Description */
|
/* Privacy - Photo Library Additions Usage Description */
|
||||||
"NSPhotoLibraryAddUsageDescription" = "A SimpleX-nek hozzáférésre van szüksége a Galériához a rögzített és fogadott média mentéséhez";
|
"NSPhotoLibraryAddUsageDescription" = "A SimpleXnek galéria-hozzáférésre van szüksége a rögzített és fogadott média mentéséhez";
|
||||||
|
|
||||||
|
|||||||
@@ -175,9 +175,24 @@
|
|||||||
/* time interval */
|
/* time interval */
|
||||||
"%d days" = "%d giorni";
|
"%d days" = "%d giorni";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) are still being downloaded." = "%d file è/sono ancora in scaricamento.";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) failed to download." = "%d file ha/hanno fallito lo scaricamento.";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) were deleted." = "%d file è/sono stato/i eliminato/i.";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) were not downloaded." = "%d file non è/sono stato/i scaricato/i.";
|
||||||
|
|
||||||
/* time interval */
|
/* time interval */
|
||||||
"%d hours" = "%d ore";
|
"%d hours" = "%d ore";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"%d messages not forwarded" = "%d messaggi non inoltrati";
|
||||||
|
|
||||||
/* time interval */
|
/* time interval */
|
||||||
"%d min" = "%d min";
|
"%d min" = "%d min";
|
||||||
|
|
||||||
@@ -457,7 +472,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"All new messages from %@ will be hidden!" = "Tutti i nuovi messaggi da %@ verrranno nascosti!";
|
"All new messages from %@ will be hidden!" = "Tutti i nuovi messaggi da %@ verrranno nascosti!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* profile dropdown */
|
||||||
"All profiles" = "Tutti gli profili";
|
"All profiles" = "Tutti gli profili";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -580,6 +595,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"App passcode is replaced with self-destruct passcode." = "Il codice di accesso dell'app viene sostituito da un codice di autodistruzione.";
|
"App passcode is replaced with self-destruct passcode." = "Il codice di accesso dell'app viene sostituito da un codice di autodistruzione.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"App session" = "Sessione dell'app";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"App version" = "Versione dell'app";
|
"App version" = "Versione dell'app";
|
||||||
|
|
||||||
@@ -676,15 +694,30 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Bad message ID" = "ID del messaggio errato";
|
"Bad message ID" = "ID del messaggio errato";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better calls" = "Chiamate migliorate";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Better groups" = "Gruppi migliorati";
|
"Better groups" = "Gruppi migliorati";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better message dates." = "Date dei messaggi migliorate.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Better messages" = "Messaggi migliorati";
|
"Better messages" = "Messaggi migliorati";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Better networking" = "Rete migliorata";
|
"Better networking" = "Rete migliorata";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better notifications" = "Notifiche migliorate";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better security ✅" = "Sicurezza migliorata ✅";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better user experience" = "Esperienza utente migliorata";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Black" = "Nero";
|
"Black" = "Nero";
|
||||||
|
|
||||||
@@ -849,7 +882,7 @@
|
|||||||
"changed role of %@ to %@" = "ha cambiato il ruolo di %1$@ in %2$@";
|
"changed role of %@ to %@" = "ha cambiato il ruolo di %1$@ in %2$@";
|
||||||
|
|
||||||
/* rcv group event chat item */
|
/* rcv group event chat item */
|
||||||
"changed your role to %@" = "cambiato il tuo ruolo in %@";
|
"changed your role to %@" = "ha cambiato il tuo ruolo in %@";
|
||||||
|
|
||||||
/* chat item text */
|
/* chat item text */
|
||||||
"changing address for %@…" = "cambio indirizzo per %@…";
|
"changing address for %@…" = "cambio indirizzo per %@…";
|
||||||
@@ -899,6 +932,9 @@
|
|||||||
/* alert message */
|
/* alert message */
|
||||||
"Chat preferences were changed." = "Le preferenze della chat sono state cambiate.";
|
"Chat preferences were changed." = "Le preferenze della chat sono state cambiate.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Chat profile" = "Profilo utente";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chat theme" = "Tema della chat";
|
"Chat theme" = "Tema della chat";
|
||||||
|
|
||||||
@@ -1271,6 +1307,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Custom time" = "Tempo personalizzato";
|
"Custom time" = "Tempo personalizzato";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Customizable message shape." = "Forma dei messaggi personalizzabile.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Customize theme" = "Personalizza il tema";
|
"Customize theme" = "Personalizza il tema";
|
||||||
|
|
||||||
@@ -1461,6 +1500,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Delete old database?" = "Eliminare il database vecchio?";
|
"Delete old database?" = "Eliminare il database vecchio?";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Delete or moderate up to 200 messages." = "Elimina o modera fino a 200 messaggi.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Delete pending connection?" = "Eliminare la connessione in attesa?";
|
"Delete pending connection?" = "Eliminare la connessione in attesa?";
|
||||||
|
|
||||||
@@ -1623,6 +1665,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Do NOT send messages directly, even if your or destination server does not support private routing." = "NON inviare messaggi direttamente, anche se il tuo server o quello di destinazione non supporta l'instradamento privato.";
|
"Do NOT send messages directly, even if your or destination server does not support private routing." = "NON inviare messaggi direttamente, anche se il tuo server o quello di destinazione non supporta l'instradamento privato.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Do not use credentials with proxy." = "Non usare credenziali con proxy.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Do NOT use private routing." = "NON usare l'instradamento privato.";
|
"Do NOT use private routing." = "NON usare l'instradamento privato.";
|
||||||
|
|
||||||
@@ -1654,6 +1699,9 @@
|
|||||||
/* server test step */
|
/* server test step */
|
||||||
"Download file" = "Scarica file";
|
"Download file" = "Scarica file";
|
||||||
|
|
||||||
|
/* alert action */
|
||||||
|
"Download files" = "Scarica i file";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Downloaded" = "Scaricato";
|
"Downloaded" = "Scaricato";
|
||||||
|
|
||||||
@@ -2020,7 +2068,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error switching profile" = "Errore nel cambio di profilo";
|
"Error switching profile" = "Errore nel cambio di profilo";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* alertTitle */
|
||||||
"Error switching profile!" = "Errore nel cambio di profilo!";
|
"Error switching profile!" = "Errore nel cambio di profilo!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -2047,8 +2095,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error: " = "Errore: ";
|
"Error: " = "Errore: ";
|
||||||
|
|
||||||
/* file error text
|
/* alert message */
|
||||||
snd error text */
|
|
||||||
"Error: %@" = "Errore: %@";
|
"Error: %@" = "Errore: %@";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -2108,6 +2155,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"File error" = "Errore del file";
|
"File error" = "Errore del file";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"File errors:\n%@" = "Errori di file:\n%@";
|
||||||
|
|
||||||
/* file error text */
|
/* file error text */
|
||||||
"File not found - most likely file was deleted or cancelled." = "File non trovato - probabilmente è stato eliminato o annullato.";
|
"File not found - most likely file was deleted or cancelled." = "File non trovato - probabilmente è stato eliminato o annullato.";
|
||||||
|
|
||||||
@@ -2189,9 +2239,21 @@
|
|||||||
/* chat item action */
|
/* chat item action */
|
||||||
"Forward" = "Inoltra";
|
"Forward" = "Inoltra";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Forward %d message(s)?" = "Inoltrare %d messaggio/i?";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Forward and save messages" = "Inoltra e salva i messaggi";
|
"Forward and save messages" = "Inoltra e salva i messaggi";
|
||||||
|
|
||||||
|
/* alert action */
|
||||||
|
"Forward messages" = "Inoltra i messaggi";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Forward messages without files?" = "Inoltrare i messaggi senza file?";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Forward up to 20 messages at once." = "Inoltra fino a 20 messaggi alla volta.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"forwarded" = "inoltrato";
|
"forwarded" = "inoltrato";
|
||||||
|
|
||||||
@@ -2201,6 +2263,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Forwarded from" = "Inoltrato da";
|
"Forwarded from" = "Inoltrato da";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Forwarding %lld messages" = "Inoltro di %lld messaggi";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Forwarding server %@ failed to connect to destination server %@. Please try later." = "Il server di inoltro %@ non è riuscito a connettersi al server di destinazione %@. Riprova più tardi.";
|
"Forwarding server %@ failed to connect to destination server %@. Please try later." = "Il server di inoltro %@ non è riuscito a connettersi al server di destinazione %@. Riprova più tardi.";
|
||||||
|
|
||||||
@@ -2429,6 +2494,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Importing archive" = "Importazione archivio";
|
"Importing archive" = "Importazione archivio";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Improved delivery, reduced traffic usage.\nMore improvements are coming soon!" = "Consegna migliorata, utilizzo di traffico ridotto.\nAltri miglioramenti sono in arrivo!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Improved message delivery" = "Consegna dei messaggi migliorata";
|
"Improved message delivery" = "Consegna dei messaggi migliorata";
|
||||||
|
|
||||||
@@ -2588,6 +2656,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "Il portachiavi di iOS verrà usato per archiviare in modo sicuro la password dopo il riavvio dell'app o la modifica della password; consentirà di ricevere notifiche push.";
|
"iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "Il portachiavi di iOS verrà usato per archiviare in modo sicuro la password dopo il riavvio dell'app o la modifica della password; consentirà di ricevere notifiche push.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"IP address" = "Indirizzo IP";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Irreversible message deletion" = "Eliminazione irreversibile del messaggio";
|
"Irreversible message deletion" = "Eliminazione irreversibile del messaggio";
|
||||||
|
|
||||||
@@ -2873,6 +2944,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Messages sent" = "Messaggi inviati";
|
"Messages sent" = "Messaggi inviati";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Messages were deleted after you selected them." = "I messaggi sono stati eliminati dopo che li hai selezionati.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* 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." = "I messaggi, i file e le chiamate sono protetti da **crittografia end-to-end** con perfect forward secrecy, ripudio e recupero da intrusione.";
|
"Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." = "I messaggi, i file e le chiamate sono protetti da **crittografia end-to-end** con perfect forward secrecy, ripudio e recupero da intrusione.";
|
||||||
|
|
||||||
@@ -3026,6 +3100,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"New passphrase…" = "Nuova password…";
|
"New passphrase…" = "Nuova password…";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"New SOCKS credentials will be used every time you start the app." = "Le nuove credenziali SOCKS verranno usate ogni volta che avvii l'app.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"New SOCKS credentials will be used for each server." = "Le nuove credenziali SOCKS verranno usate per ogni server.";
|
||||||
|
|
||||||
/* pref value */
|
/* pref value */
|
||||||
"no" = "no";
|
"no" = "no";
|
||||||
|
|
||||||
@@ -3068,6 +3148,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"No network connection" = "Nessuna connessione di rete";
|
"No network connection" = "Nessuna connessione di rete";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"No permission to record speech" = "Nessuna autorizzazione per registrare l'audio";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"No permission to record video" = "Nessuna autorizzazione per registrare il video";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"No permission to record voice message" = "Nessuna autorizzazione per registrare messaggi vocali";
|
"No permission to record voice message" = "Nessuna autorizzazione per registrare messaggi vocali";
|
||||||
|
|
||||||
@@ -3083,6 +3169,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Nothing selected" = "Nessuna selezione";
|
"Nothing selected" = "Nessuna selezione";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Nothing to forward!" = "Niente da inoltrare!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Notifications" = "Notifiche";
|
"Notifications" = "Notifiche";
|
||||||
|
|
||||||
@@ -3235,6 +3324,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"other errors" = "altri errori";
|
"other errors" = "altri errori";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Other file errors:\n%@" = "Altri errori di file:\n%@";
|
||||||
|
|
||||||
/* member role */
|
/* member role */
|
||||||
"owner" = "proprietario";
|
"owner" = "proprietario";
|
||||||
|
|
||||||
@@ -3256,6 +3348,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Passcode set!" = "Codice di accesso impostato!";
|
"Passcode set!" = "Codice di accesso impostato!";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Password" = "Password";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Password to show" = "Password per mostrare";
|
"Password to show" = "Password per mostrare";
|
||||||
|
|
||||||
@@ -3352,6 +3447,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Polish interface" = "Interfaccia polacca";
|
"Polish interface" = "Interfaccia polacca";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Port" = "Porta";
|
||||||
|
|
||||||
/* server test error */
|
/* server test error */
|
||||||
"Possibly, certificate fingerprint in server address is incorrect" = "Probabilmente l'impronta del certificato nell'indirizzo del server è sbagliata";
|
"Possibly, certificate fingerprint in server address is incorrect" = "Probabilmente l'impronta del certificato nell'indirizzo del server è sbagliata";
|
||||||
|
|
||||||
@@ -3463,6 +3561,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Proxied servers" = "Server via proxy";
|
"Proxied servers" = "Server via proxy";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Proxy requires password" = "Il proxy richiede una password";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Push notifications" = "Notifiche push";
|
"Push notifications" = "Notifiche push";
|
||||||
|
|
||||||
@@ -3804,6 +3905,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Saved WebRTC ICE servers will be removed" = "I server WebRTC ICE salvati verranno rimossi";
|
"Saved WebRTC ICE servers will be removed" = "I server WebRTC ICE salvati verranno rimossi";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Saving %lld messages" = "Salvataggio di %lld messaggi";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Scale" = "Scala";
|
"Scale" = "Scala";
|
||||||
|
|
||||||
@@ -4002,6 +4106,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Sent via proxy" = "Inviato via proxy";
|
"Sent via proxy" = "Inviato via proxy";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Server" = "Server";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Server address" = "Indirizzo server";
|
"Server address" = "Indirizzo server";
|
||||||
|
|
||||||
@@ -4191,6 +4298,9 @@
|
|||||||
/* simplex link type */
|
/* simplex link type */
|
||||||
"SimpleX one-time invitation" = "Invito SimpleX una tantum";
|
"SimpleX one-time invitation" = "Invito SimpleX una tantum";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"SimpleX protocols reviewed by Trail of Bits." = "Protocolli di SimpleX esaminati da Trail of Bits.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Simplified incognito mode" = "Modalità incognito semplificata";
|
"Simplified incognito mode" = "Modalità incognito semplificata";
|
||||||
|
|
||||||
@@ -4209,6 +4319,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"SMP server" = "Server SMP";
|
"SMP server" = "Server SMP";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"SOCKS proxy" = "Proxy SOCKS";
|
||||||
|
|
||||||
/* blur media */
|
/* blur media */
|
||||||
"Soft" = "Leggera";
|
"Soft" = "Leggera";
|
||||||
|
|
||||||
@@ -4308,6 +4421,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Support SimpleX Chat" = "Supporta SimpleX Chat";
|
"Support SimpleX Chat" = "Supporta SimpleX Chat";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Switch audio and video during the call." = "Cambia tra audio e video durante la chiamata.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Switch chat profile for 1-time invitations." = "Cambia profilo di chat per inviti una tantum.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"System" = "Sistema";
|
"System" = "Sistema";
|
||||||
|
|
||||||
@@ -4527,6 +4646,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"To protect your IP address, private routing uses your SMP servers to deliver messages." = "Per proteggere il tuo indirizzo IP, l'instradamento privato usa i tuoi server SMP per consegnare i messaggi.";
|
"To protect your IP address, private routing uses your SMP servers to deliver messages." = "Per proteggere il tuo indirizzo IP, l'instradamento privato usa i tuoi server SMP per consegnare i messaggi.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"To record speech please grant permission to use Microphone." = "Per registrare l'audio, concedi l'autorizzazione di usare il microfono.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"To record video please grant permission to use Camera." = "Per registrare il video, concedi l'autorizzazione di usare la fotocamera.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"To record voice message please grant permission to use Microphone." = "Per registrare un messaggio vocale, concedi l'autorizzazione all'uso del microfono.";
|
"To record voice message please grant permission to use Microphone." = "Per registrare un messaggio vocale, concedi l'autorizzazione all'uso del microfono.";
|
||||||
|
|
||||||
@@ -4743,6 +4868,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Use SimpleX Chat servers?" = "Usare i server di SimpleX Chat?";
|
"Use SimpleX Chat servers?" = "Usare i server di SimpleX Chat?";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Use SOCKS proxy" = "Usa proxy SOCKS";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Use the app while in the call." = "Usa l'app mentre sei in chiamata.";
|
"Use the app while in the call." = "Usa l'app mentre sei in chiamata.";
|
||||||
|
|
||||||
@@ -4750,10 +4878,10 @@
|
|||||||
"Use the app with one hand." = "Usa l'app con una mano sola.";
|
"Use the app with one hand." = "Usa l'app con una mano sola.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"User profile" = "Profilo utente";
|
"User selection" = "Selezione utente";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"User selection" = "Selezione utente";
|
"Username" = "Nome utente";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Using SimpleX Chat servers." = "Utilizzo dei server SimpleX Chat.";
|
"Using SimpleX Chat servers." = "Utilizzo dei server SimpleX Chat.";
|
||||||
@@ -4956,9 +5084,6 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"you" = "tu";
|
"you" = "tu";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"You" = "Tu";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"You **must not** use the same database on two devices." = "**Non devi** usare lo stesso database su due dispositivi.";
|
"You **must not** use the same database on two devices." = "**Non devi** usare lo stesso database su due dispositivi.";
|
||||||
|
|
||||||
@@ -5211,6 +5336,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your contacts will remain connected." = "I tuoi contatti resteranno connessi.";
|
"Your contacts will remain connected." = "I tuoi contatti resteranno connessi.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Your credentials may be sent unencrypted." = "Le credenziali potrebbero essere inviate in chiaro.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your current chat database will be DELETED and REPLACED with the imported one." = "Il tuo attuale database della chat verrà ELIMINATO e SOSTITUITO con quello importato.";
|
"Your current chat database will be DELETED and REPLACED with the imported one." = "Il tuo attuale database della chat verrà ELIMINATO e SOSTITUITO con quello importato.";
|
||||||
|
|
||||||
|
|||||||
@@ -701,6 +701,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chat preferences" = "チャット設定";
|
"Chat preferences" = "チャット設定";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Chat profile" = "ユーザープロフィール";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chats" = "チャット";
|
"Chats" = "チャット";
|
||||||
|
|
||||||
@@ -1470,7 +1473,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error stopping chat" = "チャット停止にエラー発生";
|
"Error stopping chat" = "チャット停止にエラー発生";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* alertTitle */
|
||||||
"Error switching profile!" = "プロフィール切り替えにエラー発生!";
|
"Error switching profile!" = "プロフィール切り替えにエラー発生!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -1491,8 +1494,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error: " = "エラー : ";
|
"Error: " = "エラー : ";
|
||||||
|
|
||||||
/* file error text
|
/* alert message */
|
||||||
snd error text */
|
|
||||||
"Error: %@" = "エラー : %@";
|
"Error: %@" = "エラー : %@";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -2065,6 +2067,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Messages & files" = "メッセージ & ファイル";
|
"Messages & files" = "メッセージ & ファイル";
|
||||||
|
|
||||||
|
/* 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." = "メッセージ、ファイル、通話は、前方秘匿性、否認可能性および侵入復元性を備えた**エンドツーエンドの暗号化**によって保護されます。";
|
||||||
|
|
||||||
|
/* 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." = "メッセージ、ファイル、通話は、前方秘匿性、否認可能性および侵入復元性を備えた**耐量子E2E暗号化**によって保護されます。";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Migrating database archive…" = "データベースのアーカイブを移行しています…";
|
"Migrating database archive…" = "データベースのアーカイブを移行しています…";
|
||||||
|
|
||||||
@@ -3242,9 +3250,6 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Use SimpleX Chat servers?" = "SimpleX チャット サーバーを使用しますか?";
|
"Use SimpleX Chat servers?" = "SimpleX チャット サーバーを使用しますか?";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"User profile" = "ユーザープロフィール";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Using SimpleX Chat servers." = "SimpleX チャット サーバーを使用する。";
|
"Using SimpleX Chat servers." = "SimpleX チャット サーバーを使用する。";
|
||||||
|
|
||||||
@@ -3362,9 +3367,6 @@
|
|||||||
/* pref value */
|
/* pref value */
|
||||||
"yes" = "はい";
|
"yes" = "はい";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"You" = "あなた";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"You accepted connection" = "接続を承認しました";
|
"You accepted connection" = "接続を承認しました";
|
||||||
|
|
||||||
|
|||||||
@@ -175,9 +175,24 @@
|
|||||||
/* time interval */
|
/* time interval */
|
||||||
"%d days" = "%d dagen";
|
"%d days" = "%d dagen";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) are still being downloaded." = "%d bestand(en) worden nog gedownload.";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) failed to download." = "%d bestand(en) konden niet worden gedownload.";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) were deleted." = "%d bestand(en) zijn verwijderd.";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) were not downloaded." = "%d bestand(en) zijn niet gedownload.";
|
||||||
|
|
||||||
/* time interval */
|
/* time interval */
|
||||||
"%d hours" = "%d uren";
|
"%d hours" = "%d uren";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"%d messages not forwarded" = "%d berichten niet doorgestuurd";
|
||||||
|
|
||||||
/* time interval */
|
/* time interval */
|
||||||
"%d min" = "%d min";
|
"%d min" = "%d min";
|
||||||
|
|
||||||
@@ -457,7 +472,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"All new messages from %@ will be hidden!" = "Alle nieuwe berichten van %@ worden verborgen!";
|
"All new messages from %@ will be hidden!" = "Alle nieuwe berichten van %@ worden verborgen!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* profile dropdown */
|
||||||
"All profiles" = "Alle profielen";
|
"All profiles" = "Alle profielen";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -580,6 +595,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"App passcode is replaced with self-destruct passcode." = "De app-toegangscode wordt vervangen door een zelfvernietigings wachtwoord.";
|
"App passcode is replaced with self-destruct passcode." = "De app-toegangscode wordt vervangen door een zelfvernietigings wachtwoord.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"App session" = "Appsessie";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"App version" = "App versie";
|
"App version" = "App versie";
|
||||||
|
|
||||||
@@ -676,15 +694,30 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Bad message ID" = "Onjuiste bericht-ID";
|
"Bad message ID" = "Onjuiste bericht-ID";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better calls" = "Betere gesprekken";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Better groups" = "Betere groepen";
|
"Better groups" = "Betere groepen";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better message dates." = "Betere datums voor berichten.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Better messages" = "Betere berichten";
|
"Better messages" = "Betere berichten";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Better networking" = "Beter netwerk";
|
"Better networking" = "Beter netwerk";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better notifications" = "Betere meldingen";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better security ✅" = "Betere beveiliging ✅";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Better user experience" = "Betere gebruikerservaring";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Black" = "Zwart";
|
"Black" = "Zwart";
|
||||||
|
|
||||||
@@ -899,6 +932,9 @@
|
|||||||
/* alert message */
|
/* alert message */
|
||||||
"Chat preferences were changed." = "Chatvoorkeuren zijn gewijzigd.";
|
"Chat preferences were changed." = "Chatvoorkeuren zijn gewijzigd.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Chat profile" = "Gebruikers profiel";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chat theme" = "Chat thema";
|
"Chat theme" = "Chat thema";
|
||||||
|
|
||||||
@@ -963,7 +999,7 @@
|
|||||||
"complete" = "compleet";
|
"complete" = "compleet";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Completed" = "voltooid";
|
"Completed" = "Voltooid";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Configure ICE servers" = "ICE servers configureren";
|
"Configure ICE servers" = "ICE servers configureren";
|
||||||
@@ -1271,6 +1307,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Custom time" = "Aangepaste tijd";
|
"Custom time" = "Aangepaste tijd";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Customizable message shape." = "Aanpasbare berichtvorm.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Customize theme" = "Thema aanpassen";
|
"Customize theme" = "Thema aanpassen";
|
||||||
|
|
||||||
@@ -1461,6 +1500,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Delete old database?" = "Oude database verwijderen?";
|
"Delete old database?" = "Oude database verwijderen?";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Delete or moderate up to 200 messages." = "Maximaal 200 berichten verwijderen of modereren.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Delete pending connection?" = "Wachtende verbinding verwijderen?";
|
"Delete pending connection?" = "Wachtende verbinding verwijderen?";
|
||||||
|
|
||||||
@@ -1623,6 +1665,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Do NOT send messages directly, even if your or destination server does not support private routing." = "Stuur GEEN berichten rechtstreeks, zelfs als uw of de bestemmingsserver geen privéroutering ondersteunt.";
|
"Do NOT send messages directly, even if your or destination server does not support private routing." = "Stuur GEEN berichten rechtstreeks, zelfs als uw of de bestemmingsserver geen privéroutering ondersteunt.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Do not use credentials with proxy." = "Gebruik geen inloggegevens met proxy.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Do NOT use private routing." = "Gebruik GEEN privéroutering.";
|
"Do NOT use private routing." = "Gebruik GEEN privéroutering.";
|
||||||
|
|
||||||
@@ -1654,6 +1699,9 @@
|
|||||||
/* server test step */
|
/* server test step */
|
||||||
"Download file" = "Download bestand";
|
"Download file" = "Download bestand";
|
||||||
|
|
||||||
|
/* alert action */
|
||||||
|
"Download files" = "‐Bestanden downloaden";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Downloaded" = "Gedownload";
|
"Downloaded" = "Gedownload";
|
||||||
|
|
||||||
@@ -2020,7 +2068,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error switching profile" = "Fout bij wisselen van profiel";
|
"Error switching profile" = "Fout bij wisselen van profiel";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* alertTitle */
|
||||||
"Error switching profile!" = "Fout bij wisselen van profiel!";
|
"Error switching profile!" = "Fout bij wisselen van profiel!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -2047,8 +2095,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error: " = "Fout: ";
|
"Error: " = "Fout: ";
|
||||||
|
|
||||||
/* file error text
|
/* alert message */
|
||||||
snd error text */
|
|
||||||
"Error: %@" = "Fout: %@";
|
"Error: %@" = "Fout: %@";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -2108,6 +2155,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"File error" = "Bestandsfout";
|
"File error" = "Bestandsfout";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"File errors:\n%@" = "Bestandsfouten:\n%@";
|
||||||
|
|
||||||
/* file error text */
|
/* file error text */
|
||||||
"File not found - most likely file was deleted or cancelled." = "Bestand niet gevonden - hoogstwaarschijnlijk is het bestand verwijderd of geannuleerd.";
|
"File not found - most likely file was deleted or cancelled." = "Bestand niet gevonden - hoogstwaarschijnlijk is het bestand verwijderd of geannuleerd.";
|
||||||
|
|
||||||
@@ -2189,9 +2239,21 @@
|
|||||||
/* chat item action */
|
/* chat item action */
|
||||||
"Forward" = "Doorsturen";
|
"Forward" = "Doorsturen";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Forward %d message(s)?" = "%d bericht(en) doorsturen?";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Forward and save messages" = "Berichten doorsturen en opslaan";
|
"Forward and save messages" = "Berichten doorsturen en opslaan";
|
||||||
|
|
||||||
|
/* alert action */
|
||||||
|
"Forward messages" = "Berichten doorsturen";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Forward messages without files?" = "Berichten doorsturen zonder bestanden?";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Forward up to 20 messages at once." = "Stuur maximaal 20 berichten tegelijk door.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"forwarded" = "doorgestuurd";
|
"forwarded" = "doorgestuurd";
|
||||||
|
|
||||||
@@ -2201,6 +2263,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Forwarded from" = "Doorgestuurd vanuit";
|
"Forwarded from" = "Doorgestuurd vanuit";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Forwarding %lld messages" = "%lld berichten doorsturen";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Forwarding server %@ failed to connect to destination server %@. Please try later." = "De doorstuurserver %@ kon geen verbinding maken met de bestemmingsserver %@. Probeer het later opnieuw.";
|
"Forwarding server %@ failed to connect to destination server %@. Please try later." = "De doorstuurserver %@ kon geen verbinding maken met de bestemmingsserver %@. Probeer het later opnieuw.";
|
||||||
|
|
||||||
@@ -2429,6 +2494,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Importing archive" = "Archief importeren";
|
"Importing archive" = "Archief importeren";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Improved delivery, reduced traffic usage.\nMore improvements are coming soon!" = "Verbeterde levering, minder data gebruik.\nBinnenkort meer verbeteringen!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Improved message delivery" = "Verbeterde berichtbezorging";
|
"Improved message delivery" = "Verbeterde berichtbezorging";
|
||||||
|
|
||||||
@@ -2588,6 +2656,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "iOS-keychain wordt gebruikt om het wachtwoord veilig op te slaan nadat u de app opnieuw hebt opgestart of het wachtwoord hebt gewijzigd, hiermee kunt u push meldingen ontvangen.";
|
"iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "iOS-keychain wordt gebruikt om het wachtwoord veilig op te slaan nadat u de app opnieuw hebt opgestart of het wachtwoord hebt gewijzigd, hiermee kunt u push meldingen ontvangen.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"IP address" = "IP-adres";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Irreversible message deletion" = "Onomkeerbare berichtverwijdering";
|
"Irreversible message deletion" = "Onomkeerbare berichtverwijdering";
|
||||||
|
|
||||||
@@ -2873,6 +2944,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Messages sent" = "Berichten verzonden";
|
"Messages sent" = "Berichten verzonden";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Messages were deleted after you selected them." = "Berichten zijn verwijderd nadat u ze had geselecteerd.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* 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." = "Berichten, bestanden en oproepen worden beschermd door **end-to-end codering** met perfecte voorwaartse geheimhouding, afwijzing en inbraakherstel.";
|
"Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." = "Berichten, bestanden en oproepen worden beschermd door **end-to-end codering** met perfecte voorwaartse geheimhouding, afwijzing en inbraakherstel.";
|
||||||
|
|
||||||
@@ -3026,6 +3100,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"New passphrase…" = "Nieuw wachtwoord…";
|
"New passphrase…" = "Nieuw wachtwoord…";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"New SOCKS credentials will be used every time you start the app." = "Elke keer dat u de app start, worden er nieuwe SOCKS-inloggegevens gebruikt.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"New SOCKS credentials will be used for each server." = "Voor elke server worden nieuwe SOCKS-inloggegevens gebruikt.";
|
||||||
|
|
||||||
/* pref value */
|
/* pref value */
|
||||||
"no" = "Nee";
|
"no" = "Nee";
|
||||||
|
|
||||||
@@ -3068,6 +3148,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"No network connection" = "Geen netwerkverbinding";
|
"No network connection" = "Geen netwerkverbinding";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"No permission to record speech" = "Geen toestemming om spraak op te nemen";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"No permission to record video" = "Geen toestemming om video op te nemen";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"No permission to record voice message" = "Geen toestemming om spraakbericht op te nemen";
|
"No permission to record voice message" = "Geen toestemming om spraakbericht op te nemen";
|
||||||
|
|
||||||
@@ -3083,6 +3169,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Nothing selected" = "Niets geselecteerd";
|
"Nothing selected" = "Niets geselecteerd";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Nothing to forward!" = "Niets om door te sturen!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Notifications" = "Meldingen";
|
"Notifications" = "Meldingen";
|
||||||
|
|
||||||
@@ -3235,6 +3324,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"other errors" = "overige fouten";
|
"other errors" = "overige fouten";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Other file errors:\n%@" = "Andere bestandsfouten:\n%@";
|
||||||
|
|
||||||
/* member role */
|
/* member role */
|
||||||
"owner" = "Eigenaar";
|
"owner" = "Eigenaar";
|
||||||
|
|
||||||
@@ -3256,6 +3348,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Passcode set!" = "Toegangscode ingesteld!";
|
"Passcode set!" = "Toegangscode ingesteld!";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Password" = "Wachtwoord";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Password to show" = "Wachtwoord om weer te geven";
|
"Password to show" = "Wachtwoord om weer te geven";
|
||||||
|
|
||||||
@@ -3352,6 +3447,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Polish interface" = "Poolse interface";
|
"Polish interface" = "Poolse interface";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Port" = "Poort";
|
||||||
|
|
||||||
/* server test error */
|
/* server test error */
|
||||||
"Possibly, certificate fingerprint in server address is incorrect" = "Mogelijk is de certificaat vingerafdruk in het server adres onjuist";
|
"Possibly, certificate fingerprint in server address is incorrect" = "Mogelijk is de certificaat vingerafdruk in het server adres onjuist";
|
||||||
|
|
||||||
@@ -3463,6 +3561,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Proxied servers" = "Proxied servers";
|
"Proxied servers" = "Proxied servers";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Proxy requires password" = "Proxy vereist wachtwoord";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Push notifications" = "Push meldingen";
|
"Push notifications" = "Push meldingen";
|
||||||
|
|
||||||
@@ -3804,6 +3905,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Saved WebRTC ICE servers will be removed" = "Opgeslagen WebRTC ICE servers worden verwijderd";
|
"Saved WebRTC ICE servers will be removed" = "Opgeslagen WebRTC ICE servers worden verwijderd";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Saving %lld messages" = "%lld berichten opslaan";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Scale" = "Schaal";
|
"Scale" = "Schaal";
|
||||||
|
|
||||||
@@ -4002,6 +4106,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Sent via proxy" = "Verzonden via proxy";
|
"Sent via proxy" = "Verzonden via proxy";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Server" = "Server";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Server address" = "Server adres";
|
"Server address" = "Server adres";
|
||||||
|
|
||||||
@@ -4191,6 +4298,9 @@
|
|||||||
/* simplex link type */
|
/* simplex link type */
|
||||||
"SimpleX one-time invitation" = "Eenmalige SimpleX uitnodiging";
|
"SimpleX one-time invitation" = "Eenmalige SimpleX uitnodiging";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"SimpleX protocols reviewed by Trail of Bits." = "SimpleX-protocollen beoordeeld door Trail of Bits.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Simplified incognito mode" = "Vereenvoudigde incognitomodus";
|
"Simplified incognito mode" = "Vereenvoudigde incognitomodus";
|
||||||
|
|
||||||
@@ -4209,6 +4319,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"SMP server" = "SMP server";
|
"SMP server" = "SMP server";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"SOCKS proxy" = "SOCKS proxy";
|
||||||
|
|
||||||
/* blur media */
|
/* blur media */
|
||||||
"Soft" = "Soft";
|
"Soft" = "Soft";
|
||||||
|
|
||||||
@@ -4297,23 +4410,32 @@
|
|||||||
"Submit" = "Indienen";
|
"Submit" = "Indienen";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Subscribed" = "Ingeschreven";
|
"Subscribed" = "Subscribed";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Subscription errors" = "Inschrijving fouten";
|
"Subscription errors" = "Subscription fouten";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Subscriptions ignored" = "Inschrijvingen genegeerd";
|
"Subscriptions ignored" = "Subscriptions genegeerd";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Support SimpleX Chat" = "Ondersteuning van SimpleX Chat";
|
"Support SimpleX Chat" = "Ondersteuning van SimpleX Chat";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Switch audio and video during the call." = "Wisselen tussen audio en video tijdens het gesprek.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Switch chat profile for 1-time invitations." = "Wijzig chatprofiel voor eenmalige uitnodigingen.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"System" = "Systeem";
|
"System" = "Systeem";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"System authentication" = "Systeem authenticatie";
|
"System authentication" = "Systeem authenticatie";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Tail" = "Staart";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Take picture" = "Foto nemen";
|
"Take picture" = "Foto nemen";
|
||||||
|
|
||||||
@@ -4524,6 +4646,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"To protect your IP address, private routing uses your SMP servers to deliver messages." = "Om uw IP-adres te beschermen, gebruikt privéroutering uw SMP-servers om berichten te bezorgen.";
|
"To protect your IP address, private routing uses your SMP servers to deliver messages." = "Om uw IP-adres te beschermen, gebruikt privéroutering uw SMP-servers om berichten te bezorgen.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"To record speech please grant permission to use Microphone." = "Geef toestemming om de microfoon te gebruiken om spraak op te nemen.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"To record video please grant permission to use Camera." = "Om video op te nemen, dient u toestemming te geven om de camera te gebruiken.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"To record voice message please grant permission to use Microphone." = "Geef toestemming om de microfoon te gebruiken om een spraakbericht op te nemen.";
|
"To record voice message please grant permission to use Microphone." = "Geef toestemming om de microfoon te gebruiken om een spraakbericht op te nemen.";
|
||||||
|
|
||||||
@@ -4740,6 +4868,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Use SimpleX Chat servers?" = "SimpleX Chat servers gebruiken?";
|
"Use SimpleX Chat servers?" = "SimpleX Chat servers gebruiken?";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Use SOCKS proxy" = "Gebruik SOCKS proxy";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Use the app while in the call." = "Gebruik de app tijdens het gesprek.";
|
"Use the app while in the call." = "Gebruik de app tijdens het gesprek.";
|
||||||
|
|
||||||
@@ -4747,10 +4878,10 @@
|
|||||||
"Use the app with one hand." = "Gebruik de app met één hand.";
|
"Use the app with one hand." = "Gebruik de app met één hand.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"User profile" = "Gebruikers profiel";
|
"User selection" = "Gebruikersselectie";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"User selection" = "Gebruikersselectie";
|
"Username" = "Gebruikersnaam";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Using SimpleX Chat servers." = "SimpleX Chat servers gebruiken.";
|
"Using SimpleX Chat servers." = "SimpleX Chat servers gebruiken.";
|
||||||
@@ -4953,9 +5084,6 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"you" = "jij";
|
"you" = "jij";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"You" = "Jij";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"You **must not** use the same database on two devices." = "U **mag** niet dezelfde database op twee apparaten gebruiken.";
|
"You **must not** use the same database on two devices." = "U **mag** niet dezelfde database op twee apparaten gebruiken.";
|
||||||
|
|
||||||
@@ -5005,7 +5133,7 @@
|
|||||||
"You are not connected to these servers. Private routing is used to deliver messages to them." = "U bent niet verbonden met deze servers. Privéroutering wordt gebruikt om berichten bij hen af te leveren.";
|
"You are not connected to these servers. Private routing is used to deliver messages to them." = "U bent niet verbonden met deze servers. Privéroutering wordt gebruikt om berichten bij hen af te leveren.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"you are observer" = "jij bent waarnemer";
|
"you are observer" = "je bent waarnemer";
|
||||||
|
|
||||||
/* snd group event chat item */
|
/* snd group event chat item */
|
||||||
"you blocked %@" = "je hebt %@ geblokkeerd";
|
"you blocked %@" = "je hebt %@ geblokkeerd";
|
||||||
@@ -5107,7 +5235,7 @@
|
|||||||
"You joined this group. Connecting to inviting group member." = "Je bent lid geworden van deze groep. Verbinding maken met uitnodigend groepslid.";
|
"You joined this group. Connecting to inviting group member." = "Je bent lid geworden van deze groep. Verbinding maken met uitnodigend groepslid.";
|
||||||
|
|
||||||
/* snd group event chat item */
|
/* snd group event chat item */
|
||||||
"you left" = "jij bent vertrokken";
|
"you left" = "je bent vertrokken";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"You may migrate the exported database." = "U kunt de geëxporteerde database migreren.";
|
"You may migrate the exported database." = "U kunt de geëxporteerde database migreren.";
|
||||||
@@ -5208,6 +5336,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your contacts will remain connected." = "Uw contacten blijven verbonden.";
|
"Your contacts will remain connected." = "Uw contacten blijven verbonden.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Your credentials may be sent unencrypted." = "Uw inloggegevens worden mogelijk niet-versleuteld verzonden.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your current chat database will be DELETED and REPLACED with the imported one." = "Uw huidige chat database wordt VERWIJDERD en VERVANGEN door de geïmporteerde.";
|
"Your current chat database will be DELETED and REPLACED with the imported one." = "Uw huidige chat database wordt VERWIJDERD en VERVANGEN door de geïmporteerde.";
|
||||||
|
|
||||||
|
|||||||
@@ -160,6 +160,9 @@
|
|||||||
/* notification title */
|
/* notification title */
|
||||||
"%@ wants to connect!" = "%@ chce się połączyć!";
|
"%@ wants to connect!" = "%@ chce się połączyć!";
|
||||||
|
|
||||||
|
/* format for date separator in chat */
|
||||||
|
"%@, %@" = "%1$@, %2$@";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"%@, %@ and %lld members" = "%@, %@ i %lld członków";
|
"%@, %@ and %lld members" = "%@, %@ i %lld członków";
|
||||||
|
|
||||||
@@ -172,9 +175,24 @@
|
|||||||
/* time interval */
|
/* time interval */
|
||||||
"%d days" = "%d dni";
|
"%d days" = "%d dni";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) are still being downloaded." = "%d plik(ów) jest dalej pobieranych.";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) failed to download." = "%d plik(ów) nie udało się pobrać.";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) were deleted." = "%d plik(ów) zostało usuniętych.";
|
||||||
|
|
||||||
|
/* forward confirmation reason */
|
||||||
|
"%d file(s) were not downloaded." = "%d plik(ów) nie zostało pobranych.";
|
||||||
|
|
||||||
/* time interval */
|
/* time interval */
|
||||||
"%d hours" = "%d godzin";
|
"%d hours" = "%d godzin";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"%d messages not forwarded" = "%d wiadomości nie przekazanych";
|
||||||
|
|
||||||
/* time interval */
|
/* time interval */
|
||||||
"%d min" = "%d min";
|
"%d min" = "%d min";
|
||||||
|
|
||||||
@@ -454,7 +472,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"All new messages from %@ will be hidden!" = "Wszystkie nowe wiadomości z %@ zostaną ukryte!";
|
"All new messages from %@ will be hidden!" = "Wszystkie nowe wiadomości z %@ zostaną ukryte!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* profile dropdown */
|
||||||
"All profiles" = "Wszystkie profile";
|
"All profiles" = "Wszystkie profile";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -577,6 +595,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"App passcode is replaced with self-destruct passcode." = "Pin aplikacji został zastąpiony pinem samozniszczenia.";
|
"App passcode is replaced with self-destruct passcode." = "Pin aplikacji został zastąpiony pinem samozniszczenia.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"App session" = "Sesja aplikacji";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"App version" = "Wersja aplikacji";
|
"App version" = "Wersja aplikacji";
|
||||||
|
|
||||||
@@ -649,6 +670,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Auto-accept images" = "Automatyczne akceptowanie obrazów";
|
"Auto-accept images" = "Automatyczne akceptowanie obrazów";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Auto-accept settings" = "Ustawienia automatycznej akceptacji";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Back" = "Wstecz";
|
"Back" = "Wstecz";
|
||||||
|
|
||||||
@@ -890,6 +914,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chat preferences" = "Preferencje czatu";
|
"Chat preferences" = "Preferencje czatu";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Chat preferences were changed." = "Preferencje czatu zostały zmienione.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Chat profile" = "Profil użytkownika";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Chat theme" = "Motyw czatu";
|
"Chat theme" = "Motyw czatu";
|
||||||
|
|
||||||
@@ -1178,6 +1208,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Core version: v%@" = "Wersja rdzenia: v%@";
|
"Core version: v%@" = "Wersja rdzenia: v%@";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Corner" = "Róg";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Correct name to %@?" = "Poprawić imię na %@?";
|
"Correct name to %@?" = "Poprawić imię na %@?";
|
||||||
|
|
||||||
@@ -1611,6 +1644,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Do NOT send messages directly, even if your or destination server does not support private routing." = "NIE wysyłaj wiadomości bezpośrednio, nawet jeśli serwer docelowy nie obsługuje prywatnego trasowania.";
|
"Do NOT send messages directly, even if your or destination server does not support private routing." = "NIE wysyłaj wiadomości bezpośrednio, nawet jeśli serwer docelowy nie obsługuje prywatnego trasowania.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Do not use credentials with proxy." = "Nie używaj danych logowania do proxy.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Do NOT use private routing." = "NIE używaj prywatnego trasowania.";
|
"Do NOT use private routing." = "NIE używaj prywatnego trasowania.";
|
||||||
|
|
||||||
@@ -1642,6 +1678,9 @@
|
|||||||
/* server test step */
|
/* server test step */
|
||||||
"Download file" = "Pobierz plik";
|
"Download file" = "Pobierz plik";
|
||||||
|
|
||||||
|
/* alert action */
|
||||||
|
"Download files" = "Pobierz pliki";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Downloaded" = "Pobrane";
|
"Downloaded" = "Pobrane";
|
||||||
|
|
||||||
@@ -1858,12 +1897,18 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error changing address" = "Błąd zmiany adresu";
|
"Error changing address" = "Błąd zmiany adresu";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Error changing connection profile" = "Błąd zmiany połączenia profilu";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error changing role" = "Błąd zmiany roli";
|
"Error changing role" = "Błąd zmiany roli";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error changing setting" = "Błąd zmiany ustawienia";
|
"Error changing setting" = "Błąd zmiany ustawienia";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Error changing to incognito!" = "Błąd zmiany na incognito!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error connecting to forwarding server %@. Please try later." = "Błąd połączenia z serwerem przekierowania %@. Spróbuj ponownie później.";
|
"Error connecting to forwarding server %@. Please try later." = "Błąd połączenia z serwerem przekierowania %@. Spróbuj ponownie później.";
|
||||||
|
|
||||||
@@ -1936,6 +1981,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error loading %@ servers" = "Błąd ładowania %@ serwerów";
|
"Error loading %@ servers" = "Błąd ładowania %@ serwerów";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Error migrating settings" = "Błąd migracji ustawień";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error opening chat" = "Błąd otwierania czatu";
|
"Error opening chat" = "Błąd otwierania czatu";
|
||||||
|
|
||||||
@@ -1997,6 +2045,9 @@
|
|||||||
"Error stopping chat" = "Błąd zatrzymania czatu";
|
"Error stopping chat" = "Błąd zatrzymania czatu";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
|
"Error switching profile" = "Błąd zmiany profilu";
|
||||||
|
|
||||||
|
/* alertTitle */
|
||||||
"Error switching profile!" = "Błąd przełączania profilu!";
|
"Error switching profile!" = "Błąd przełączania profilu!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -2023,8 +2074,7 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Error: " = "Błąd: ";
|
"Error: " = "Błąd: ";
|
||||||
|
|
||||||
/* file error text
|
/* alert message */
|
||||||
snd error text */
|
|
||||||
"Error: %@" = "Błąd: %@";
|
"Error: %@" = "Błąd: %@";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
@@ -2084,6 +2134,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"File error" = "Błąd pliku";
|
"File error" = "Błąd pliku";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"File errors:\n%@" = "Błędy pliku:\n%@";
|
||||||
|
|
||||||
/* file error text */
|
/* file error text */
|
||||||
"File not found - most likely file was deleted or cancelled." = "Nie odnaleziono pliku - najprawdopodobniej plik został usunięty lub anulowany.";
|
"File not found - most likely file was deleted or cancelled." = "Nie odnaleziono pliku - najprawdopodobniej plik został usunięty lub anulowany.";
|
||||||
|
|
||||||
@@ -2165,9 +2218,18 @@
|
|||||||
/* chat item action */
|
/* chat item action */
|
||||||
"Forward" = "Przekaż dalej";
|
"Forward" = "Przekaż dalej";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Forward %d message(s)?" = "Przekazać %d wiadomość(i)?";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Forward and save messages" = "Przesyłaj dalej i zapisuj wiadomości";
|
"Forward and save messages" = "Przesyłaj dalej i zapisuj wiadomości";
|
||||||
|
|
||||||
|
/* alert action */
|
||||||
|
"Forward messages" = "Przekaż wiadomości";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Forward messages without files?" = "Przekazać wiadomości bez plików?";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"forwarded" = "przekazane dalej";
|
"forwarded" = "przekazane dalej";
|
||||||
|
|
||||||
@@ -2177,6 +2239,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Forwarded from" = "Przekazane dalej od";
|
"Forwarded from" = "Przekazane dalej od";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Forwarding %lld messages" = "Przekazywanie %lld wiadomości";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Forwarding server %@ failed to connect to destination server %@. Please try later." = "Serwer przekazujący %@ nie mógł połączyć się z serwerem docelowym %@. Spróbuj ponownie później.";
|
"Forwarding server %@ failed to connect to destination server %@. Please try later." = "Serwer przekazujący %@ nie mógł połączyć się z serwerem docelowym %@. Spróbuj ponownie później.";
|
||||||
|
|
||||||
@@ -2564,6 +2629,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "iOS Keychain będzie używany do bezpiecznego przechowywania hasła po ponownym uruchomieniu aplikacji lub zmianie hasła - pozwoli to na otrzymywanie powiadomień push.";
|
"iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "iOS Keychain będzie używany do bezpiecznego przechowywania hasła po ponownym uruchomieniu aplikacji lub zmianie hasła - pozwoli to na otrzymywanie powiadomień push.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"IP address" = "Adres IP";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Irreversible message deletion" = "Nieodwracalne usuwanie wiadomości";
|
"Irreversible message deletion" = "Nieodwracalne usuwanie wiadomości";
|
||||||
|
|
||||||
@@ -2816,6 +2884,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Message servers" = "Serwery wiadomości";
|
"Message servers" = "Serwery wiadomości";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Message shape" = "Kształt wiadomości";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Message source remains private." = "Źródło wiadomości pozostaje prywatne.";
|
"Message source remains private." = "Źródło wiadomości pozostaje prywatne.";
|
||||||
|
|
||||||
@@ -2846,6 +2917,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Messages sent" = "Wysłane wiadomości";
|
"Messages sent" = "Wysłane wiadomości";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Messages were deleted after you selected them." = "Wiadomości zostały usunięte po wybraniu ich.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* 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." = "Wiadomości, pliki i połączenia są chronione przez **szyfrowanie end-to-end** z doskonałym utajnianiem z wyprzedzeniem i odzyskiem po złamaniu.";
|
"Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." = "Wiadomości, pliki i połączenia są chronione przez **szyfrowanie end-to-end** z doskonałym utajnianiem z wyprzedzeniem i odzyskiem po złamaniu.";
|
||||||
|
|
||||||
@@ -2999,6 +3073,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"New passphrase…" = "Nowe hasło…";
|
"New passphrase…" = "Nowe hasło…";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"New SOCKS credentials will be used every time you start the app." = "Nowe poświadczenia SOCKS będą używane przy każdym uruchomieniu aplikacji.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"New SOCKS credentials will be used for each server." = "Dla każdego serwera zostaną użyte nowe poświadczenia SOCKS.";
|
||||||
|
|
||||||
/* pref value */
|
/* pref value */
|
||||||
"no" = "nie";
|
"no" = "nie";
|
||||||
|
|
||||||
@@ -3041,6 +3121,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"No network connection" = "Brak połączenia z siecią";
|
"No network connection" = "Brak połączenia z siecią";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"No permission to record speech" = "Brak zezwoleń do nagrania rozmowy";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"No permission to record video" = "Brak zezwoleń do nagrania wideo";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"No permission to record voice message" = "Brak uprawnień do nagrywania wiadomości głosowej";
|
"No permission to record voice message" = "Brak uprawnień do nagrywania wiadomości głosowej";
|
||||||
|
|
||||||
@@ -3056,6 +3142,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Nothing selected" = "Nic nie jest zaznaczone";
|
"Nothing selected" = "Nic nie jest zaznaczone";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Nothing to forward!" = "Nic do przekazania!";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Notifications" = "Powiadomienia";
|
"Notifications" = "Powiadomienia";
|
||||||
|
|
||||||
@@ -3208,6 +3297,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"other errors" = "inne błędy";
|
"other errors" = "inne błędy";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Other file errors:\n%@" = "Inne błędy pliku:\n%@";
|
||||||
|
|
||||||
/* member role */
|
/* member role */
|
||||||
"owner" = "właściciel";
|
"owner" = "właściciel";
|
||||||
|
|
||||||
@@ -3229,6 +3321,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Passcode set!" = "Pin ustawiony!";
|
"Passcode set!" = "Pin ustawiony!";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Password" = "Hasło";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Password to show" = "Hasło do wyświetlenia";
|
"Password to show" = "Hasło do wyświetlenia";
|
||||||
|
|
||||||
@@ -3325,6 +3420,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Polish interface" = "Polski interfejs";
|
"Polish interface" = "Polski interfejs";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Port" = "Port";
|
||||||
|
|
||||||
/* server test error */
|
/* server test error */
|
||||||
"Possibly, certificate fingerprint in server address is incorrect" = "Możliwe, że odcisk palca certyfikatu w adresie serwera jest nieprawidłowy";
|
"Possibly, certificate fingerprint in server address is incorrect" = "Możliwe, że odcisk palca certyfikatu w adresie serwera jest nieprawidłowy";
|
||||||
|
|
||||||
@@ -3436,6 +3534,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Proxied servers" = "Serwery trasowane przez proxy";
|
"Proxied servers" = "Serwery trasowane przez proxy";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Proxy requires password" = "Proxy wymaga hasła";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Push notifications" = "Powiadomienia push";
|
"Push notifications" = "Powiadomienia push";
|
||||||
|
|
||||||
@@ -3581,6 +3682,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Remove" = "Usuń";
|
"Remove" = "Usuń";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Remove archive?" = "Usunąć archiwum?";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Remove image" = "Usuń obraz";
|
"Remove image" = "Usuń obraz";
|
||||||
|
|
||||||
@@ -3753,6 +3857,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Save welcome message?" = "Zapisać wiadomość powitalną?";
|
"Save welcome message?" = "Zapisać wiadomość powitalną?";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Save your profile?" = "Zapisać Twój profil?";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"saved" = "zapisane";
|
"saved" = "zapisane";
|
||||||
|
|
||||||
@@ -3771,6 +3878,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Saved WebRTC ICE servers will be removed" = "Zapisane serwery WebRTC ICE zostaną usunięte";
|
"Saved WebRTC ICE servers will be removed" = "Zapisane serwery WebRTC ICE zostaną usunięte";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Saving %lld messages" = "Zapisywanie %lld wiadomości";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Scale" = "Skaluj";
|
"Scale" = "Skaluj";
|
||||||
|
|
||||||
@@ -3834,6 +3944,9 @@
|
|||||||
/* chat item action */
|
/* chat item action */
|
||||||
"Select" = "Wybierz";
|
"Select" = "Wybierz";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Select chat profile" = "Wybierz profil czatu";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Selected %lld" = "Zaznaczono %lld";
|
"Selected %lld" = "Zaznaczono %lld";
|
||||||
|
|
||||||
@@ -3966,6 +4079,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Sent via proxy" = "Wysłano przez proxy";
|
"Sent via proxy" = "Wysłano przez proxy";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Server" = "Serwer";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Server address" = "Adres serwera";
|
"Server address" = "Adres serwera";
|
||||||
|
|
||||||
@@ -4047,6 +4163,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Settings" = "Ustawienia";
|
"Settings" = "Ustawienia";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Settings were changed." = "Ustawienia zostały zmienione.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Shape profile images" = "Kształtuj obrazy profilowe";
|
"Shape profile images" = "Kształtuj obrazy profilowe";
|
||||||
|
|
||||||
@@ -4068,6 +4187,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Share link" = "Udostępnij link";
|
"Share link" = "Udostępnij link";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Share profile" = "Udostępnij profil";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Share this 1-time invite link" = "Udostępnij ten jednorazowy link";
|
"Share this 1-time invite link" = "Udostępnij ten jednorazowy link";
|
||||||
|
|
||||||
@@ -4167,9 +4289,15 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"SMP server" = "Serwer SMP";
|
"SMP server" = "Serwer SMP";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"SOCKS proxy" = "Proxy SOCKS";
|
||||||
|
|
||||||
/* blur media */
|
/* blur media */
|
||||||
"Soft" = "Łagodny";
|
"Soft" = "Łagodny";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Some app settings were not migrated." = "Niektóre ustawienia aplikacji nie zostały zmigrowane.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Some file(s) were not exported:" = "Niektóre plik(i) nie zostały wyeksportowane:";
|
"Some file(s) were not exported:" = "Niektóre plik(i) nie zostały wyeksportowane:";
|
||||||
|
|
||||||
@@ -4269,6 +4397,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"System authentication" = "Uwierzytelnianie systemu";
|
"System authentication" = "Uwierzytelnianie systemu";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Tail" = "Ogon";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Take picture" = "Zrób zdjęcie";
|
"Take picture" = "Zrób zdjęcie";
|
||||||
|
|
||||||
@@ -4398,6 +4529,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"The text you pasted is not a SimpleX link." = "Tekst, który wkleiłeś nie jest linkiem SimpleX.";
|
"The text you pasted is not a SimpleX link." = "Tekst, który wkleiłeś nie jest linkiem SimpleX.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"The uploaded database archive will be permanently removed from the servers." = "Przesłane archiwum bazy danych zostanie trwale usunięte z serwerów.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Themes" = "Motywy";
|
"Themes" = "Motywy";
|
||||||
|
|
||||||
@@ -4476,6 +4610,12 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"To protect your IP address, private routing uses your SMP servers to deliver messages." = "Aby chronić Twój adres IP, prywatne trasowanie używa Twoich serwerów SMP, aby dostarczyć wiadomości.";
|
"To protect your IP address, private routing uses your SMP servers to deliver messages." = "Aby chronić Twój adres IP, prywatne trasowanie używa Twoich serwerów SMP, aby dostarczyć wiadomości.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"To record speech please grant permission to use Microphone." = "Aby nagrać rozmowę, proszę zezwolić na użycie Mikrofonu.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"To record video please grant permission to use Camera." = "Aby nagrać wideo, proszę zezwolić na użycie Aparatu.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"To record voice message please grant permission to use Microphone." = "Aby nagrać wiadomość głosową należy udzielić zgody na użycie Mikrofonu.";
|
"To record voice message please grant permission to use Microphone." = "Aby nagrać wiadomość głosową należy udzielić zgody na użycie Mikrofonu.";
|
||||||
|
|
||||||
@@ -4692,6 +4832,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Use SimpleX Chat servers?" = "Użyć serwerów SimpleX Chat?";
|
"Use SimpleX Chat servers?" = "Użyć serwerów SimpleX Chat?";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Use SOCKS proxy" = "Użyj proxy SOCKS";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Use the app while in the call." = "Używaj aplikacji podczas połączenia.";
|
"Use the app while in the call." = "Używaj aplikacji podczas połączenia.";
|
||||||
|
|
||||||
@@ -4699,10 +4842,10 @@
|
|||||||
"Use the app with one hand." = "Korzystaj z aplikacji jedną ręką.";
|
"Use the app with one hand." = "Korzystaj z aplikacji jedną ręką.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"User profile" = "Profil użytkownika";
|
"User selection" = "Wybór użytkownika";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"User selection" = "Wybór użytkownika";
|
"Username" = "Nazwa użytkownika";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Using SimpleX Chat servers." = "Używanie serwerów SimpleX Chat.";
|
"Using SimpleX Chat servers." = "Używanie serwerów SimpleX Chat.";
|
||||||
@@ -4905,9 +5048,6 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"you" = "Ty";
|
"you" = "Ty";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"You" = "Ty";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"You **must not** use the same database on two devices." = "**Nie możesz** używać tej samej bazy na dwóch urządzeniach.";
|
"You **must not** use the same database on two devices." = "**Nie możesz** używać tej samej bazy na dwóch urządzeniach.";
|
||||||
|
|
||||||
@@ -5142,9 +5282,15 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your chat database is not encrypted - set passphrase to encrypt it." = "Baza danych czatu nie jest szyfrowana - ustaw hasło, aby ją zaszyfrować.";
|
"Your chat database is not encrypted - set passphrase to encrypt it." = "Baza danych czatu nie jest szyfrowana - ustaw hasło, aby ją zaszyfrować.";
|
||||||
|
|
||||||
|
/* alert title */
|
||||||
|
"Your chat preferences" = "Twoje preferencje czatu";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your chat profiles" = "Twoje profile czatu";
|
"Your chat profiles" = "Twoje profile czatu";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile." = "Twoje połączenie zostało przeniesione do %@, ale podczas przekierowywania do profilu wystąpił nieoczekiwany błąd.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your contact sent a file that is larger than currently supported maximum size (%@)." = "Twój kontakt wysłał plik, który jest większy niż obecnie obsługiwany maksymalny rozmiar (%@).";
|
"Your contact sent a file that is larger than currently supported maximum size (%@)." = "Twój kontakt wysłał plik, który jest większy niż obecnie obsługiwany maksymalny rozmiar (%@).";
|
||||||
|
|
||||||
@@ -5154,6 +5300,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your contacts will remain connected." = "Twoje kontakty pozostaną połączone.";
|
"Your contacts will remain connected." = "Twoje kontakty pozostaną połączone.";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
|
"Your credentials may be sent unencrypted." = "Twoje poświadczenia mogą zostać wysłane niezaszyfrowane.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your current chat database will be DELETED and REPLACED with the imported one." = "Twoja obecna baza danych czatu zostanie usunięta i zastąpiona zaimportowaną.";
|
"Your current chat database will be DELETED and REPLACED with the imported one." = "Twoja obecna baza danych czatu zostanie usunięta i zastąpiona zaimportowaną.";
|
||||||
|
|
||||||
@@ -5178,6 +5327,9 @@
|
|||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Twój profil jest przechowywany na urządzeniu i udostępniany tylko Twoim kontaktom. Serwery SimpleX nie mogą zobaczyć Twojego profilu.";
|
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Twój profil jest przechowywany na urządzeniu i udostępniany tylko Twoim kontaktom. Serwery SimpleX nie mogą zobaczyć Twojego profilu.";
|
||||||
|
|
||||||
|
/* alert message */
|
||||||
|
"Your profile was changed. If you save it, the updated profile will be sent to all your contacts." = "Twój profil został zmieniony. Jeśli go zapiszesz, zaktualizowany profil zostanie wysłany do wszystkich kontaktów.";
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"Your profile, contacts and delivered messages are stored on your device." = "Twój profil, kontakty i dostarczone wiadomości są przechowywane na Twoim urządzeniu.";
|
"Your profile, contacts and delivered messages are stored on your device." = "Twój profil, kontakty i dostarczone wiadomości są przechowywane na Twoim urządzeniu.";
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user